Exemplo n.º 1
0
char *
gen_conflict_path_wrapper (const char *repo_id, int version,
                           const char *head, const char *in_repo_path,
                           const char *original_path)
{
    char *modifier;
    gint64 mtime;

    /* XXX: this function is only used in client, so store_id is always
     * the same as repo_id. This can be changed if it's also called in
     * server.
     */
    if (get_file_modifier_mtime (repo_id, repo_id, version, head, in_repo_path,
                                 &modifier, &mtime) < 0)
        return NULL;

    return gen_conflict_path (original_path, modifier, mtime);
}
Exemplo n.º 2
0
/*
 * Per entry merge function for D/F (and/or rename) conflicts.  In the
 * cases we can cleanly resolve D/F conflicts, process_entry() can
 * clean out all the files below the directory for us.  All D/F
 * conflict cases must be handled here at the end to make sure any
 * directories that can be cleaned out, are.
 */
static int process_df_entry(struct merge_options *o,
                            const char *path,
                            struct stage_data *entry)
{
    int clean_merge = 1;
    unsigned o_mode = entry->stages[1].mode;
    unsigned a_mode = entry->stages[2].mode;
    unsigned b_mode = entry->stages[3].mode;
    unsigned char *o_sha = o_mode ? entry->stages[1].sha : NULL;
    unsigned char *a_sha = a_mode ? entry->stages[2].sha : NULL;
    unsigned char *b_sha = b_mode ? entry->stages[3].sha : NULL;
    SeafStat st;
    char *real_path = g_build_path(PATH_SEPERATOR, o->worktree, path, NULL);
    char *new_path = NULL;
    char *conflict_suffix = NULL;

    entry->processed = 1;
    if (o_sha && (!a_sha || !b_sha)) {
        clean_merge = 0;
        /* Modify/delete; deleted side may have put a directory in the way */
        if (b_sha) {
            if (seaf_stat (real_path, &st) == 0 && S_ISDIR(st.st_mode)) {
                /* D/F conflict. */
                /* If b is an empty dir, don't check it out. */
                if (S_ISDIR(b_mode))
                    goto out;

                if (!o->collect_blocks_only) {
                    conflict_suffix = get_last_changer_of_file (o->remote_head,
                                                                path);
                    if (!conflict_suffix)
                        conflict_suffix = g_strdup(o->branch2);
                    new_path = gen_conflict_path (path, conflict_suffix);
                }

                update_file(o, 0, b_sha, b_mode, new_path);
                g_free (new_path);
                g_free (conflict_suffix);
            } else {
                /* Modify/Delete conflict. */
                update_file(o, 0, b_sha, b_mode, path);
            }
        }
        /* If the conflicting file is mine, it's already in the work tree.
         * And the conflicting dir should have proper suffix.
         * So nothing need to be processed here.
         */
    } else if (!o_sha && !!a_sha != !!b_sha) {
        /* directory -> (directory, file) */
        if (b_sha) {
            if (seaf_stat (real_path, &st) == 0 && S_ISDIR(st.st_mode)) {
                /* D/F conflict. */
                clean_merge = 0;

                if (S_ISDIR (b_mode))
                    goto out;

                if (!o->collect_blocks_only) {
                    conflict_suffix = get_last_changer_of_file (o->remote_head,
                                                                path);
                    if (!conflict_suffix)
                        conflict_suffix = g_strdup(o->branch2);
                    new_path = gen_conflict_path (path, conflict_suffix);
                }

                update_file(o, 0, b_sha, b_mode, new_path);
                g_free (new_path);
                g_free (conflict_suffix);
            } else {
                /* Clean merge. */
                update_file(o, 1, b_sha, b_mode, path);
            }
        }
    } else {
        entry->processed = 0;
        g_free(real_path);
        return 1; /* not handled; assume clean until processed */
    }

out:
    g_free(real_path);
    return clean_merge;
}
Exemplo n.º 3
0
/* Per entry merge function */
static int process_entry(struct merge_options *o,
                         const char *path,
                         struct stage_data *entry)
{
    /*
      printf("processing entry, clean cache: %s\n", index_only ? "yes": "no");
      print_index_entry("\tpath: ", entry);
    */
    int clean_merge = 1;
    unsigned o_mode = entry->stages[1].mode;
    unsigned a_mode = entry->stages[2].mode;
    unsigned b_mode = entry->stages[3].mode;
    unsigned char *o_sha = o_mode ? entry->stages[1].sha : NULL;
    unsigned char *a_sha = a_mode ? entry->stages[2].sha : NULL;
    unsigned char *b_sha = b_mode ? entry->stages[3].sha : NULL;
    unsigned int a_ctime = entry->stages[2].ctime;
    unsigned int a_mtime = entry->stages[2].mtime;

    /* if (entry->rename_df_conflict_info) */
    /*  return 1; /\* Such cases are handled elsewhere. *\/ */

    entry->processed = 1;
    if (o_sha && (!a_sha || !b_sha)) {
        /* Case A: Deleted in one */
        if ((!a_sha && !b_sha) ||
            (!b_sha && memcmp(o_sha, a_sha, 20) == 0 && o_mode == a_mode) ||
            (!a_sha && memcmp(o_sha, b_sha, 20) == 0 && o_mode == b_mode)) {
            /* Deleted in both or deleted in one and
             * unchanged in the other */
            /* do not touch working file if it did not exist */
            /* do not remove working file if it's changed. */
            remove_file(o, 1, path, !a_sha, a_ctime, a_mtime);
        } else if (g_hash_table_lookup(o->current_directory_set,
                                       path)) {
            /* file -> (file, directory), the file side. */
            entry->processed = 0;
            return 1;
        } else {
            /* Deleted in one and changed in the other */
            /* or directory -> (file, directory), directory side */
            clean_merge = 0;
            handle_delete_modify(o, path, path,
                                 a_sha, a_mode, b_sha, b_mode);
        }

    } else if ((!o_sha && a_sha && !b_sha) ||
               (!o_sha && !a_sha && b_sha)) {
        /* Case B: Added in one. */
        if (g_hash_table_lookup(o->current_directory_set, path)) {
            /* directory -> (file, directory), file side. */
            entry->processed = 0;
            return 1;
        } else {
            /* Added in one */
            /* or file -> (file, directory), directory side */
            if (b_sha)
                clean_merge = update_file(o, 1, b_sha, b_mode, path);
            else
                /* For my file, just set index entry to stage 0,
                 * without updating worktree. */
                update_file_flags (o, a_sha, a_mode, path, 1, 0);
        }
    } else if (a_sha && b_sha) {
        /* Case C: Added in both (check for same permissions) and */
        /* case D: Modified in both, but differently. */
        if (memcmp(a_sha, b_sha, 20) != 0 || a_mode != b_mode) {
            char *new_path = NULL;
            char *conflict_suffix = NULL;

            clean_merge = 0;
            if (S_ISDIR (b_mode))
                goto out;

            if (!o->collect_blocks_only) {
                conflict_suffix = get_last_changer_of_file (o->remote_head, path);
                if (!conflict_suffix)
                    conflict_suffix = g_strdup(o->branch2);
                new_path = gen_conflict_path (path, conflict_suffix);
            }

            /* Dont update index. */
            /* Keep my version, rename other's version. */
            update_file_flags(o, b_sha, b_mode, new_path, 0, 1);
            g_free (new_path);
            g_free (conflict_suffix);
        } else {
            update_file_flags (o, a_sha, b_mode, path, 1, 0);
        }
    } else if (!o_sha && !a_sha && !b_sha) {
        /*
         * this entry was deleted altogether. a_mode == 0 means
         * we had that path and want to actively remove it.
         */
        remove_file(o, 1, path, !a_mode, a_ctime, a_mtime);
    } else
        g_error("Fatal merge failure, shouldn't happen.");

out:
    return clean_merge;
}