update-index.con commit Merge http://www.kernel.org/pub/scm/gitk/gitk (069b20a)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7#include "strbuf.h"
   8#include "quote.h"
   9
  10/*
  11 * Default to not allowing changes to the list of files. The
  12 * tool doesn't actually care, but this makes it harder to add
  13 * files to the revision control by mistake by doing something
  14 * like "git-update-index *" and suddenly having all the object
  15 * files be revision controlled.
  16 */
  17static int allow_add;
  18static int allow_remove;
  19static int allow_replace;
  20static int allow_unmerged; /* --refresh needing merge is not error */
  21static int not_new; /* --refresh not having working tree files is not error */
  22static int quiet; /* --refresh needing update is not error */
  23static int info_only;
  24static int force_remove;
  25static int verbose;
  26
  27/* Three functions to allow overloaded pointer return; see linux/err.h */
  28static inline void *ERR_PTR(long error)
  29{
  30        return (void *) error;
  31}
  32
  33static inline long PTR_ERR(const void *ptr)
  34{
  35        return (long) ptr;
  36}
  37
  38static inline long IS_ERR(const void *ptr)
  39{
  40        return (unsigned long)ptr > (unsigned long)-1000L;
  41}
  42
  43static void report(const char *fmt, ...)
  44{
  45        va_list vp;
  46
  47        if (!verbose)
  48                return;
  49
  50        va_start(vp, fmt);
  51        vprintf(fmt, vp);
  52        putchar('\n');
  53        va_end(vp);
  54}
  55
  56static int add_file_to_cache(const char *path)
  57{
  58        int size, namelen, option, status;
  59        struct cache_entry *ce;
  60        struct stat st;
  61
  62        status = lstat(path, &st);
  63        if (status < 0 || S_ISDIR(st.st_mode)) {
  64                /* When we used to have "path" and now we want to add
  65                 * "path/file", we need a way to remove "path" before
  66                 * being able to add "path/file".  However,
  67                 * "git-update-index --remove path" would not work.
  68                 * --force-remove can be used but this is more user
  69                 * friendly, especially since we can do the opposite
  70                 * case just fine without --force-remove.
  71                 */
  72                if (status == 0 || (errno == ENOENT || errno == ENOTDIR)) {
  73                        if (allow_remove) {
  74                                if (remove_file_from_cache(path))
  75                                        return error("%s: cannot remove from the index",
  76                                                     path);
  77                                else
  78                                        return 0;
  79                        } else if (status < 0) {
  80                                return error("%s: does not exist and --remove not passed",
  81                                             path);
  82                        }
  83                }
  84                if (0 == status)
  85                        return error("%s: is a directory - add files inside instead",
  86                                     path);
  87                else
  88                        return error("lstat(\"%s\"): %s", path,
  89                                     strerror(errno));
  90        }
  91
  92        namelen = strlen(path);
  93        size = cache_entry_size(namelen);
  94        ce = xmalloc(size);
  95        memset(ce, 0, size);
  96        memcpy(ce->name, path, namelen);
  97        fill_stat_cache_info(ce, &st);
  98
  99        ce->ce_mode = create_ce_mode(st.st_mode);
 100        if (!trust_executable_bit) {
 101                /* If there is an existing entry, pick the mode bits
 102                 * from it.
 103                 */
 104                int pos = cache_name_pos(path, namelen);
 105                if (0 <= pos)
 106                        ce->ce_mode = active_cache[pos]->ce_mode;
 107        }
 108        ce->ce_flags = htons(namelen);
 109
 110        if (index_path(ce->sha1, path, &st, !info_only))
 111                return -1;
 112        option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
 113        option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
 114        if (add_cache_entry(ce, option))
 115                return error("%s: cannot add to the index - missing --add option?",
 116                             path);
 117        return 0;
 118}
 119
 120/*
 121 * "refresh" does not calculate a new sha1 file or bring the
 122 * cache up-to-date for mode/content changes. But what it
 123 * _does_ do is to "re-match" the stat information of a file
 124 * with the cache, so that you can refresh the cache for a
 125 * file that hasn't been changed but where the stat entry is
 126 * out of date.
 127 *
 128 * For example, you'd want to do this after doing a "git-read-tree",
 129 * to link up the stat cache details with the proper files.
 130 */
 131static struct cache_entry *refresh_entry(struct cache_entry *ce)
 132{
 133        struct stat st;
 134        struct cache_entry *updated;
 135        int changed, size;
 136
 137        if (lstat(ce->name, &st) < 0)
 138                return ERR_PTR(-errno);
 139
 140        changed = ce_match_stat(ce, &st);
 141        if (!changed)
 142                return NULL;
 143
 144        if (ce_modified(ce, &st))
 145                return ERR_PTR(-EINVAL);
 146
 147        size = ce_size(ce);
 148        updated = xmalloc(size);
 149        memcpy(updated, ce, size);
 150        fill_stat_cache_info(updated, &st);
 151        return updated;
 152}
 153
 154static int refresh_cache(void)
 155{
 156        int i;
 157        int has_errors = 0;
 158
 159        for (i = 0; i < active_nr; i++) {
 160                struct cache_entry *ce, *new;
 161                ce = active_cache[i];
 162                if (ce_stage(ce)) {
 163                        while ((i < active_nr) &&
 164                               ! strcmp(active_cache[i]->name, ce->name))
 165                                i++;
 166                        i--;
 167                        if (allow_unmerged)
 168                                continue;
 169                        printf("%s: needs merge\n", ce->name);
 170                        has_errors = 1;
 171                        continue;
 172                }
 173
 174                new = refresh_entry(ce);
 175                if (!new)
 176                        continue;
 177                if (IS_ERR(new)) {
 178                        if (not_new && PTR_ERR(new) == -ENOENT)
 179                                continue;
 180                        if (quiet)
 181                                continue;
 182                        printf("%s: needs update\n", ce->name);
 183                        has_errors = 1;
 184                        continue;
 185                }
 186                active_cache_changed = 1;
 187                /* You can NOT just free active_cache[i] here, since it
 188                 * might not be necessarily malloc()ed but can also come
 189                 * from mmap(). */
 190                active_cache[i] = new;
 191        }
 192        return has_errors;
 193}
 194
 195/*
 196 * We fundamentally don't like some paths: we don't want
 197 * dot or dot-dot anywhere, and for obvious reasons don't
 198 * want to recurse into ".git" either.
 199 *
 200 * Also, we don't want double slashes or slashes at the
 201 * end that can make pathnames ambiguous.
 202 */
 203static int verify_dotfile(const char *rest)
 204{
 205        /*
 206         * The first character was '.', but that
 207         * has already been discarded, we now test
 208         * the rest.
 209         */
 210        switch (*rest) {
 211        /* "." is not allowed */
 212        case '\0': case '/':
 213                return 0;
 214
 215        /*
 216         * ".git" followed by  NUL or slash is bad. This
 217         * shares the path end test with the ".." case.
 218         */
 219        case 'g':
 220                if (rest[1] != 'i')
 221                        break;
 222                if (rest[2] != 't')
 223                        break;
 224                rest += 2;
 225        /* fallthrough */
 226        case '.':
 227                if (rest[1] == '\0' || rest[1] == '/')
 228                        return 0;
 229        }
 230        return 1;
 231}
 232
 233static int verify_path(const char *path)
 234{
 235        char c;
 236
 237        goto inside;
 238        for (;;) {
 239                if (!c)
 240                        return 1;
 241                if (c == '/') {
 242inside:
 243                        c = *path++;
 244                        switch (c) {
 245                        default:
 246                                continue;
 247                        case '/': case '\0':
 248                                break;
 249                        case '.':
 250                                if (verify_dotfile(path))
 251                                        continue;
 252                        }
 253                        return 0;
 254                }
 255                c = *path++;
 256        }
 257}
 258
 259static int add_cacheinfo(const char *arg1, const char *arg2, const char *arg3)
 260{
 261        int size, len, option;
 262        unsigned int mode;
 263        unsigned char sha1[20];
 264        struct cache_entry *ce;
 265
 266        if (sscanf(arg1, "%o", &mode) != 1)
 267                return -1;
 268        if (get_sha1_hex(arg2, sha1))
 269                return -1;
 270        if (!verify_path(arg3))
 271                return -1;
 272
 273        len = strlen(arg3);
 274        size = cache_entry_size(len);
 275        ce = xmalloc(size);
 276        memset(ce, 0, size);
 277
 278        memcpy(ce->sha1, sha1, 20);
 279        memcpy(ce->name, arg3, len);
 280        ce->ce_flags = htons(len);
 281        ce->ce_mode = create_ce_mode(mode);
 282        option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
 283        option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
 284        if (add_cache_entry(ce, option))
 285                return error("%s: cannot add to the index - missing --add option?",
 286                             arg3);
 287        report("add '%s'", arg3);
 288        return 0;
 289}
 290
 291static int chmod_path(int flip, const char *path)
 292{
 293        int pos;
 294        struct cache_entry *ce;
 295        unsigned int mode;
 296
 297        pos = cache_name_pos(path, strlen(path));
 298        if (pos < 0)
 299                return -1;
 300        ce = active_cache[pos];
 301        mode = ntohl(ce->ce_mode);
 302        if (!S_ISREG(mode))
 303                return -1;
 304        switch (flip) {
 305        case '+':
 306                ce->ce_mode |= htonl(0111); break;
 307        case '-':
 308                ce->ce_mode &= htonl(~0111); break;
 309        default:
 310                return -1;
 311        }
 312        active_cache_changed = 1;
 313        return 0;
 314}
 315
 316static struct cache_file cache_file;
 317
 318static void update_one(const char *path, const char *prefix, int prefix_length)
 319{
 320        const char *p = prefix_path(prefix, prefix_length, path);
 321        if (!verify_path(p)) {
 322                fprintf(stderr, "Ignoring path %s\n", path);
 323                return;
 324        }
 325        if (force_remove) {
 326                if (remove_file_from_cache(p))
 327                        die("git-update-index: unable to remove %s", path);
 328                report("remove '%s'", path);
 329                return;
 330        }
 331        if (add_file_to_cache(p))
 332                die("Unable to process file %s", path);
 333        report("add '%s'", path);
 334}
 335
 336static void read_index_info(int line_termination)
 337{
 338        struct strbuf buf;
 339        strbuf_init(&buf);
 340        while (1) {
 341                char *ptr, *tab;
 342                char *path_name;
 343                unsigned char sha1[20];
 344                unsigned int mode;
 345
 346                read_line(&buf, stdin, line_termination);
 347                if (buf.eof)
 348                        break;
 349
 350                mode = strtoul(buf.buf, &ptr, 8);
 351                if (ptr == buf.buf || *ptr != ' ')
 352                        goto bad_line;
 353
 354                tab = strchr(ptr, '\t');
 355                if (!tab || tab - ptr < 41)
 356                        goto bad_line;
 357                if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
 358                        goto bad_line;
 359                ptr = tab + 1;
 360
 361                if (line_termination && ptr[0] == '"')
 362                        path_name = unquote_c_style(ptr, NULL);
 363                else
 364                        path_name = ptr;
 365
 366                if (!verify_path(path_name)) {
 367                        fprintf(stderr, "Ignoring path %s\n", path_name);
 368                        if (path_name != ptr)
 369                                free(path_name);
 370                        continue;
 371                }
 372
 373                if (!mode) {
 374                        /* mode == 0 means there is no such path -- remove */
 375                        if (remove_file_from_cache(path_name))
 376                                die("git-update-index: unable to remove %s",
 377                                    ptr);
 378                }
 379                else {
 380                        /* mode ' ' sha1 '\t' name
 381                         * ptr[-1] points at tab,
 382                         * ptr[-41] is at the beginning of sha1
 383                         */
 384                        ptr[-42] = ptr[-1] = 0;
 385                        if (add_cacheinfo(buf.buf, ptr-41, path_name))
 386                                die("git-update-index: unable to update %s",
 387                                    path_name);
 388                }
 389                if (path_name != ptr)
 390                        free(path_name);
 391                continue;
 392
 393        bad_line:
 394                die("malformed index info %s", buf.buf);
 395        }
 396}
 397
 398static const char update_index_usage[] =
 399"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--cacheinfo] [--chmod=(+|-)x] [--info-only] [--force-remove] [--stdin] [--index-info] [--ignore-missing] [-z] [--verbose] [--] <file>...";
 400
 401int main(int argc, const char **argv)
 402{
 403        int i, newfd, entries, has_errors = 0, line_termination = '\n';
 404        int allow_options = 1;
 405        int read_from_stdin = 0;
 406        const char *prefix = setup_git_directory();
 407        int prefix_length = prefix ? strlen(prefix) : 0;
 408
 409        git_config(git_default_config);
 410
 411        newfd = hold_index_file_for_update(&cache_file, get_index_file());
 412        if (newfd < 0)
 413                die("unable to create new cachefile");
 414
 415        entries = read_cache();
 416        if (entries < 0)
 417                die("cache corrupted");
 418
 419        for (i = 1 ; i < argc; i++) {
 420                const char *path = argv[i];
 421
 422                if (allow_options && *path == '-') {
 423                        if (!strcmp(path, "--")) {
 424                                allow_options = 0;
 425                                continue;
 426                        }
 427                        if (!strcmp(path, "-q")) {
 428                                quiet = 1;
 429                                continue;
 430                        }
 431                        if (!strcmp(path, "--add")) {
 432                                allow_add = 1;
 433                                continue;
 434                        }
 435                        if (!strcmp(path, "--replace")) {
 436                                allow_replace = 1;
 437                                continue;
 438                        }
 439                        if (!strcmp(path, "--remove")) {
 440                                allow_remove = 1;
 441                                continue;
 442                        }
 443                        if (!strcmp(path, "--unmerged")) {
 444                                allow_unmerged = 1;
 445                                continue;
 446                        }
 447                        if (!strcmp(path, "--refresh")) {
 448                                has_errors |= refresh_cache();
 449                                continue;
 450                        }
 451                        if (!strcmp(path, "--cacheinfo")) {
 452                                if (i+3 >= argc)
 453                                        die("git-update-index: --cacheinfo <mode> <sha1> <path>");
 454                                if (add_cacheinfo(argv[i+1], argv[i+2], argv[i+3]))
 455                                        die("git-update-index: --cacheinfo cannot add %s", argv[i+3]);
 456                                i += 3;
 457                                continue;
 458                        }
 459                        if (!strcmp(path, "--chmod=-x") ||
 460                            !strcmp(path, "--chmod=+x")) {
 461                                if (argc <= i+1)
 462                                        die("git-update-index: %s <path>", path);
 463                                if (chmod_path(path[8], argv[++i]))
 464                                        die("git-update-index: %s cannot chmod %s", path, argv[i]);
 465                                continue;
 466                        }
 467                        if (!strcmp(path, "--info-only")) {
 468                                info_only = 1;
 469                                continue;
 470                        }
 471                        if (!strcmp(path, "--force-remove")) {
 472                                force_remove = 1;
 473                                continue;
 474                        }
 475                        if (!strcmp(path, "-z")) {
 476                                line_termination = 0;
 477                                continue;
 478                        }
 479                        if (!strcmp(path, "--stdin")) {
 480                                if (i != argc - 1)
 481                                        die("--stdin must be at the end");
 482                                read_from_stdin = 1;
 483                                break;
 484                        }
 485                        if (!strcmp(path, "--index-info")) {
 486                                allow_add = allow_replace = allow_remove = 1;
 487                                read_index_info(line_termination);
 488                                continue;
 489                        }
 490                        if (!strcmp(path, "--ignore-missing")) {
 491                                not_new = 1;
 492                                continue;
 493                        }
 494                        if (!strcmp(path, "--verbose")) {
 495                                verbose = 1;
 496                                continue;
 497                        }
 498                        if (!strcmp(path, "-h") || !strcmp(path, "--help"))
 499                                usage(update_index_usage);
 500                        die("unknown option %s", path);
 501                }
 502                update_one(path, prefix, prefix_length);
 503        }
 504        if (read_from_stdin) {
 505                struct strbuf buf;
 506                strbuf_init(&buf);
 507                while (1) {
 508                        read_line(&buf, stdin, line_termination);
 509                        if (buf.eof)
 510                                break;
 511                        update_one(buf.buf, prefix, prefix_length);
 512                }
 513        }
 514        if (active_cache_changed) {
 515                if (write_cache(newfd, active_cache, active_nr) ||
 516                    commit_index_file(&cache_file))
 517                        die("Unable to write new cachefile");
 518        }
 519
 520        return has_errors ? 1 : 0;
 521}