read-tree.con commit date.c: split up dst information in the timezone table (5e2a78a)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7
   8static int stage = 0;
   9
  10static int unpack_tree(unsigned char *sha1)
  11{
  12        void *buffer;
  13        unsigned long size;
  14
  15        buffer = read_object_with_reference(sha1, "tree", &size, 0);
  16        if (!buffer)
  17                return -1;
  18        return read_tree(buffer, size, stage);
  19}
  20
  21static char *lockfile_name;
  22
  23static void remove_lock_file(void)
  24{
  25        if (lockfile_name)
  26                unlink(lockfile_name);
  27}
  28
  29static int path_matches(struct cache_entry *a, struct cache_entry *b)
  30{
  31        int len = ce_namelen(a);
  32        return ce_namelen(b) == len &&
  33                !memcmp(a->name, b->name, len);
  34}
  35
  36static int same(struct cache_entry *a, struct cache_entry *b)
  37{
  38        return a->ce_mode == b->ce_mode && 
  39                !memcmp(a->sha1, b->sha1, 20);
  40}
  41
  42
  43/*
  44 * This removes all trivial merges that don't change the tree
  45 * and collapses them to state 0.
  46 *
  47 * _Any_ other merge is left to user policy.  That includes "both
  48 * created the same file", and "both removed the same file" - which are
  49 * trivial, but the user might still want to _note_ it. 
  50 */
  51static struct cache_entry *merge_entries(struct cache_entry *a,
  52                                         struct cache_entry *b,
  53                                         struct cache_entry *c)
  54{
  55        int len = ce_namelen(a);
  56
  57        /*
  58         * Are they all the same filename? We won't do
  59         * any name merging
  60         */
  61        if (ce_namelen(b) != len ||
  62            ce_namelen(c) != len ||
  63            memcmp(a->name, b->name, len) ||
  64            memcmp(a->name, c->name, len))
  65                return NULL;
  66
  67        /*
  68         * Ok, all three entries describe the same
  69         * filename, but maybe the contents or file
  70         * mode have changed?
  71         *
  72         * The trivial cases end up being the ones where two
  73         * out of three files are the same:
  74         *  - both destinations the same, trivially take either
  75         *  - one of the destination versions hasn't changed,
  76         *    take the other.
  77         *
  78         * The "all entries exactly the same" case falls out as
  79         * a special case of any of the "two same" cases.
  80         *
  81         * Here "a" is "original", and "b" and "c" are the two
  82         * trees we are merging.
  83         */
  84        if (same(b,c))
  85                return c;
  86        if (same(a,b))
  87                return c;
  88        if (same(a,c))
  89                return b;
  90        return NULL;
  91}
  92
  93static void trivially_merge_cache(struct cache_entry **src, int nr)
  94{
  95        static struct cache_entry null_entry;
  96        struct cache_entry **dst = src;
  97        struct cache_entry *old = &null_entry;
  98
  99        while (nr) {
 100                struct cache_entry *ce, *result;
 101
 102                ce = src[0];
 103
 104                /* We throw away original cache entries except for the stat information */
 105                if (!ce_stage(ce)) {
 106                        old = ce;
 107                        src++;
 108                        nr--;
 109                        active_nr--;
 110                        continue;
 111                }
 112                if (nr > 2 && (result = merge_entries(ce, src[1], src[2])) != NULL) {
 113                        /*
 114                         * See if we can re-use the old CE directly?
 115                         * That way we get the uptodate stat info.
 116                         */
 117                        if (path_matches(result, old) && same(result, old))
 118                                *result = *old;
 119                        ce = result;
 120                        ce->ce_flags &= ~htons(CE_STAGEMASK);
 121                        src += 2;
 122                        nr -= 2;
 123                        active_nr -= 2;
 124                }
 125                *dst++ = ce;
 126                src++;
 127                nr--;
 128        }
 129}
 130
 131static void merge_stat_info(struct cache_entry **src, int nr)
 132{
 133        static struct cache_entry null_entry;
 134        struct cache_entry **dst = src;
 135        struct cache_entry *old = &null_entry;
 136
 137        while (nr) {
 138                struct cache_entry *ce;
 139
 140                ce = src[0];
 141
 142                /* We throw away original cache entries except for the stat information */
 143                if (!ce_stage(ce)) {
 144                        old = ce;
 145                        src++;
 146                        nr--;
 147                        active_nr--;
 148                        continue;
 149                }
 150                if (path_matches(ce, old) && same(ce, old))
 151                        *ce = *old;
 152                ce->ce_flags &= ~htons(CE_STAGEMASK);
 153                *dst++ = ce;
 154                src++;
 155                nr--;
 156        }
 157}
 158
 159static char *read_tree_usage = "read-tree (<sha> | -m <sha1> [<sha2> <sha3>])";
 160
 161int main(int argc, char **argv)
 162{
 163        int i, newfd, merge;
 164        unsigned char sha1[20];
 165        static char lockfile[MAXPATHLEN+1];
 166        const char *indexfile = get_index_file();
 167
 168        snprintf(lockfile, sizeof(lockfile), "%s.lock", indexfile);
 169
 170        newfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600);
 171        if (newfd < 0)
 172                die("unable to create new cachefile");
 173        atexit(remove_lock_file);
 174        lockfile_name = lockfile;
 175
 176        merge = 0;
 177        for (i = 1; i < argc; i++) {
 178                const char *arg = argv[i];
 179
 180                /* "-m" stands for "merge", meaning we start in stage 1 */
 181                if (!strcmp(arg, "-m")) {
 182                        int i;
 183                        if (stage)
 184                                die("-m needs to come first");
 185                        read_cache();
 186                        for (i = 0; i < active_nr; i++) {
 187                                if (ce_stage(active_cache[i]))
 188                                        die("you need to resolve your current index first");
 189                        }
 190                        stage = 1;
 191                        merge = 1;
 192                        continue;
 193                }
 194                if (get_sha1_hex(arg, sha1) < 0)
 195                        usage(read_tree_usage);
 196                if (stage > 3)
 197                        usage(read_tree_usage);
 198                if (unpack_tree(sha1) < 0)
 199                        die("failed to unpack tree object %s", arg);
 200                stage++;
 201        }
 202        if (merge) {
 203                switch (stage) {
 204                case 4: /* Three-way merge */
 205                        trivially_merge_cache(active_cache, active_nr);
 206                        break;
 207                case 2: /* Just read a tree, merge with old cache contents */
 208                        merge_stat_info(active_cache, active_nr);
 209                        break;
 210                default:
 211                        die("just how do you expect me to merge %d trees?", stage-1);
 212                }
 213        }
 214        if (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile))
 215                die("unable to write new index file");
 216        lockfile_name = NULL;
 217        return 0;
 218}