update-index.con commit GIT 0.99.9a (e634aec)
   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;
 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                    get_sha1_hex(ptr + 1, sha1) ||
 353                    ptr[41] != '\t')
 354                        goto bad_line;
 355
 356                ptr += 42;
 357
 358                if (line_termination && ptr[0] == '"')
 359                        path_name = unquote_c_style(ptr, NULL);
 360                else
 361                        path_name = ptr;
 362
 363                if (!verify_path(path_name)) {
 364                        fprintf(stderr, "Ignoring path %s\n", path_name);
 365                        if (path_name != ptr)
 366                                free(path_name);
 367                        continue;
 368                }
 369
 370                if (!mode) {
 371                        /* mode == 0 means there is no such path -- remove */
 372                        if (remove_file_from_cache(path_name))
 373                                die("git-update-index: unable to remove %s",
 374                                    ptr);
 375                }
 376                else {
 377                        /* mode ' ' sha1 '\t' name
 378                         * ptr[-1] points at tab,
 379                         * ptr[-41] is at the beginning of sha1
 380                         */
 381                        ptr[-42] = ptr[-1] = 0;
 382                        if (add_cacheinfo(buf.buf, ptr-41, path_name))
 383                                die("git-update-index: unable to update %s",
 384                                    path_name);
 385                }
 386                if (path_name != ptr)
 387                        free(path_name);
 388                continue;
 389
 390        bad_line:
 391                die("malformed index info %s", buf.buf);
 392        }
 393}
 394
 395static const char update_index_usage[] =
 396"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--cacheinfo] [--chmod=(+|-)x] [--info-only] [--force-remove] [--stdin] [--index-info] [--ignore-missing] [-z] [--verbose] [--] <file>...";
 397
 398int main(int argc, const char **argv)
 399{
 400        int i, newfd, entries, has_errors = 0, line_termination = '\n';
 401        int allow_options = 1;
 402        int read_from_stdin = 0;
 403        const char *prefix = setup_git_directory();
 404        int prefix_length = prefix ? strlen(prefix) : 0;
 405
 406        git_config(git_default_config);
 407
 408        newfd = hold_index_file_for_update(&cache_file, get_index_file());
 409        if (newfd < 0)
 410                die("unable to create new cachefile");
 411
 412        entries = read_cache();
 413        if (entries < 0)
 414                die("cache corrupted");
 415
 416        for (i = 1 ; i < argc; i++) {
 417                const char *path = argv[i];
 418
 419                if (allow_options && *path == '-') {
 420                        if (!strcmp(path, "--")) {
 421                                allow_options = 0;
 422                                continue;
 423                        }
 424                        if (!strcmp(path, "-q")) {
 425                                quiet = 1;
 426                                continue;
 427                        }
 428                        if (!strcmp(path, "--add")) {
 429                                allow_add = 1;
 430                                continue;
 431                        }
 432                        if (!strcmp(path, "--replace")) {
 433                                allow_replace = 1;
 434                                continue;
 435                        }
 436                        if (!strcmp(path, "--remove")) {
 437                                allow_remove = 1;
 438                                continue;
 439                        }
 440                        if (!strcmp(path, "--unmerged")) {
 441                                allow_unmerged = 1;
 442                                continue;
 443                        }
 444                        if (!strcmp(path, "--refresh")) {
 445                                has_errors |= refresh_cache();
 446                                continue;
 447                        }
 448                        if (!strcmp(path, "--cacheinfo")) {
 449                                if (i+3 >= argc)
 450                                        die("git-update-index: --cacheinfo <mode> <sha1> <path>");
 451                                if (add_cacheinfo(argv[i+1], argv[i+2], argv[i+3]))
 452                                        die("git-update-index: --cacheinfo cannot add %s", argv[i+3]);
 453                                i += 3;
 454                                continue;
 455                        }
 456                        if (!strcmp(path, "--chmod=-x") ||
 457                            !strcmp(path, "--chmod=+x")) {
 458                                if (argc <= i+1)
 459                                        die("git-update-index: %s <path>", path);
 460                                if (chmod_path(path[8], argv[++i]))
 461                                        die("git-update-index: %s cannot chmod %s", path, argv[i]);
 462                                continue;
 463                        }
 464                        if (!strcmp(path, "--info-only")) {
 465                                info_only = 1;
 466                                continue;
 467                        }
 468                        if (!strcmp(path, "--force-remove")) {
 469                                force_remove = 1;
 470                                continue;
 471                        }
 472                        if (!strcmp(path, "-z")) {
 473                                line_termination = 0;
 474                                continue;
 475                        }
 476                        if (!strcmp(path, "--stdin")) {
 477                                if (i != argc - 1)
 478                                        die("--stdin must be at the end");
 479                                read_from_stdin = 1;
 480                                break;
 481                        }
 482                        if (!strcmp(path, "--index-info")) {
 483                                allow_add = allow_replace = allow_remove = 1;
 484                                read_index_info(line_termination);
 485                                continue;
 486                        }
 487                        if (!strcmp(path, "--ignore-missing")) {
 488                                not_new = 1;
 489                                continue;
 490                        }
 491                        if (!strcmp(path, "--verbose")) {
 492                                verbose = 1;
 493                                continue;
 494                        }
 495                        if (!strcmp(path, "-h") || !strcmp(path, "--help"))
 496                                usage(update_index_usage);
 497                        die("unknown option %s", path);
 498                }
 499                update_one(path, prefix, prefix_length);
 500        }
 501        if (read_from_stdin) {
 502                struct strbuf buf;
 503                strbuf_init(&buf);
 504                while (1) {
 505                        read_line(&buf, stdin, line_termination);
 506                        if (buf.eof)
 507                                break;
 508                        update_one(buf.buf, prefix, prefix_length);
 509                }
 510        }
 511        if (active_cache_changed) {
 512                if (write_cache(newfd, active_cache, active_nr) ||
 513                    commit_index_file(&cache_file))
 514                        die("Unable to write new cachefile");
 515        }
 516
 517        return has_errors ? 1 : 0;
 518}