Esempio n. 1
0
static void update_file(int clean,
			const unsigned char *sha,
			unsigned mode,
			const char *path)
{
	update_file_flags(sha, mode, path, index_only || clean, !index_only);
}
Esempio n. 2
0
static int update_file(struct merge_options *o,
                       int clean,
                       const unsigned char *sha,
                       unsigned mode,
                       const char *path)
{
    return update_file_flags(o, sha, mode, path, clean, 1);
}
Esempio n. 3
0
static void update_file(struct merge_options *o,
			int clean,
			const unsigned char *sha,
			unsigned mode,
			const char *path)
{
	update_file_flags(o, sha, mode, path, o->call_depth || clean, !o->call_depth);
}
Esempio n. 4
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;
}
Esempio n. 5
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 = stage_sha(entry->stages[1].sha, o_mode);
	unsigned char *a_sha = stage_sha(entry->stages[2].sha, a_mode);
	unsigned char *b_sha = stage_sha(entry->stages[3].sha, b_mode);

	if (o_sha && (!a_sha || !b_sha)) {
		/* Case A: Deleted in one */
		if ((!a_sha && !b_sha) ||
		    (sha_eq(a_sha, o_sha) && !b_sha) ||
		    (!a_sha && sha_eq(b_sha, o_sha))) {
			/* Deleted in both or deleted in one and
			 * unchanged in the other */
			if (a_sha)
				output(o, 2, "Removing %s", path);
			/* do not touch working file if it did not exist */
			remove_file(o, 1, path, !a_sha);
		} else {
			/* Deleted in one and changed in the other */
			clean_merge = 0;
			if (!a_sha) {
				output(o, 1, "CONFLICT (delete/modify): %s deleted in %s "
				       "and modified in %s. Version %s of %s left in tree.",
				       path, o->branch1,
				       o->branch2, o->branch2, path);
				update_file(o, 0, b_sha, b_mode, path);
			} else {
				output(o, 1, "CONFLICT (delete/modify): %s deleted in %s "
				       "and modified in %s. Version %s of %s left in tree.",
				       path, o->branch2,
				       o->branch1, o->branch1, path);
				update_file(o, 0, a_sha, a_mode, path);
			}
		}

	} else if ((!o_sha && a_sha && !b_sha) ||
		   (!o_sha && !a_sha && b_sha)) {
		/* Case B: Added in one. */
		const char *add_branch;
		const char *other_branch;
		unsigned mode;
		const unsigned char *sha;
		const char *conf;

		if (a_sha) {
			add_branch = o->branch1;
			other_branch = o->branch2;
			mode = a_mode;
			sha = a_sha;
			conf = "file/directory";
		} else {
			add_branch = o->branch2;
			other_branch = o->branch1;
			mode = b_mode;
			sha = b_sha;
			conf = "directory/file";
		}
		if (string_list_has_string(&o->current_directory_set, path)) {
			const char *new_path = unique_path(o, path, add_branch);
			clean_merge = 0;
			output(o, 1, "CONFLICT (%s): There is a directory with name %s in %s. "
			       "Adding %s as %s",
			       conf, path, other_branch, path, new_path);
			remove_file(o, 0, path, 0);
			update_file(o, 0, sha, mode, new_path);
		} else {
			output(o, 2, "Adding %s", path);
			update_file(o, 1, sha, mode, path);
		}
	} else if (a_sha && b_sha) {
		/* Case C: Added in both (check for same permissions) and */
		/* case D: Modified in both, but differently. */
		const char *reason = "content";
		struct merge_file_info mfi;
		struct diff_filespec one, a, b;

		if (!o_sha) {
			reason = "add/add";
			o_sha = (unsigned char *)null_sha1;
		}
		output(o, 2, "Auto-merging %s", path);
		one.path = a.path = b.path = (char *)path;
		hashcpy(one.sha1, o_sha);
		one.mode = o_mode;
		hashcpy(a.sha1, a_sha);
		a.mode = a_mode;
		hashcpy(b.sha1, b_sha);
		b.mode = b_mode;

		mfi = merge_file(o, &one, &a, &b,
				 o->branch1, o->branch2);

		clean_merge = mfi.clean;
		if (mfi.clean)
			update_file(o, 1, mfi.sha, mfi.mode, path);
		else if (S_ISGITLINK(mfi.mode))
			output(o, 1, "CONFLICT (submodule): Merge conflict in %s "
			       "- needs %s", path, sha1_to_hex(b.sha1));
		else {
			output(o, 1, "CONFLICT (%s): Merge conflict in %s",
					reason, path);

			if (o->call_depth)
				update_file(o, 0, mfi.sha, mfi.mode, path);
			else
				update_file_flags(o, mfi.sha, mfi.mode, path,
					      0 /* update_cache */, 1 /* update_working_directory */);
		}
	} 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);
	} else
		die("Fatal merge failure, shouldn't happen.");

	return clean_merge;
}