0b23b9bc75fdef20839fa9ecc36eac6dd6fdb1e4
   1#include "cache.h"
   2#include "tree-walk.h"
   3
   4static const char unresolve_usage[] =
   5"git-unresolve <paths>...";
   6
   7static struct cache_file cache_file;
   8static unsigned char head_sha1[20];
   9static unsigned char merge_head_sha1[20];
  10
  11static struct cache_entry *read_one_ent(const char *which,
  12                                        unsigned char *ent, const char *path,
  13                                        int namelen, int stage)
  14{
  15        unsigned mode;
  16        unsigned char sha1[20];
  17        int size;
  18        struct cache_entry *ce;
  19
  20        if (get_tree_entry(ent, path, sha1, &mode)) {
  21                error("%s: not in %s branch.", path, which);
  22                return NULL;
  23        }
  24        if (mode == S_IFDIR) {
  25                error("%s: not a blob in %s branch.", path, which);
  26                return NULL;
  27        }
  28        size = cache_entry_size(namelen);
  29        ce = xcalloc(1, size);
  30
  31        memcpy(ce->sha1, sha1, 20);
  32        memcpy(ce->name, path, namelen);
  33        ce->ce_flags = create_ce_flags(namelen, stage);
  34        ce->ce_mode = create_ce_mode(mode);
  35        return ce;
  36}
  37
  38static int unresolve_one(const char *path)
  39{
  40        int namelen = strlen(path);
  41        int pos;
  42        int ret = 0;
  43        struct cache_entry *ce_2 = NULL, *ce_3 = NULL;
  44
  45        /* See if there is such entry in the index. */
  46        pos = cache_name_pos(path, namelen);
  47        if (pos < 0) {
  48                /* If there isn't, either it is unmerged, or
  49                 * resolved as "removed" by mistake.  We do not
  50                 * want to do anything in the former case.
  51                 */
  52                pos = -pos-1;
  53                if (pos < active_nr) {
  54                        struct cache_entry *ce = active_cache[pos];
  55                        if (ce_namelen(ce) == namelen &&
  56                            !memcmp(ce->name, path, namelen)) {
  57                                fprintf(stderr,
  58                                        "%s: skipping still unmerged path.\n",
  59                                        path);
  60                                goto free_return;
  61                        }
  62                }
  63        }
  64
  65        /* Grab blobs from given path from HEAD and MERGE_HEAD,
  66         * stuff HEAD version in stage #2,
  67         * stuff MERGE_HEAD version in stage #3.
  68         */
  69        ce_2 = read_one_ent("our", head_sha1, path, namelen, 2);
  70        ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3);
  71
  72        if (!ce_2 || !ce_3) {
  73                ret = -1;
  74                goto free_return;
  75        }
  76        if (!memcmp(ce_2->sha1, ce_3->sha1, 20) &&
  77            ce_2->ce_mode == ce_3->ce_mode) {
  78                fprintf(stderr, "%s: identical in both, skipping.\n",
  79                        path);
  80                goto free_return;
  81        }
  82
  83        remove_file_from_cache(path);
  84        if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
  85                error("%s: cannot add our version to the index.", path);
  86                ret = -1;
  87                goto free_return;
  88        }
  89        if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD))
  90                return 0;
  91        error("%s: cannot add their version to the index.", path);
  92        ret = -1;
  93 free_return:
  94        free(ce_2);
  95        free(ce_3);
  96        return ret;
  97}
  98
  99static void read_head_pointers(void)
 100{
 101        if (read_ref(git_path("HEAD"), head_sha1))
 102                die("Cannot read HEAD -- no initial commit yet?");
 103        if (read_ref(git_path("MERGE_HEAD"), merge_head_sha1)) {
 104                fprintf(stderr, "Not in the middle of a merge.\n");
 105                exit(0);
 106        }
 107}
 108
 109int main(int ac, char **av)
 110{
 111        int i;
 112        int err = 0;
 113        int newfd;
 114
 115        if (ac < 2)
 116                usage(unresolve_usage);
 117
 118        git_config(git_default_config);
 119
 120        /* Read HEAD and MERGE_HEAD; if MERGE_HEAD does not exist, we
 121         * are not doing a merge, so exit with success status.
 122         */
 123        read_head_pointers();
 124
 125        /* Otherwise we would need to update the cache. */
 126        newfd= hold_index_file_for_update(&cache_file, get_index_file());
 127        if (newfd < 0)
 128                die("unable to create new cachefile");
 129
 130        if (read_cache() < 0)
 131                die("cache corrupted");
 132
 133        for (i = 1; i < ac; i++) {
 134                char *arg = av[i];
 135                err |= unresolve_one(arg);
 136        }
 137        if (err)
 138                die("Error encountered; index not updated.");
 139
 140        if (active_cache_changed) {
 141                if (write_cache(newfd, active_cache, active_nr) ||
 142                    commit_index_file(&cache_file))
 143                        die("Unable to write new cachefile");
 144        }
 145        return 0;
 146}