~ubuntu-branches/ubuntu/edgy/git-core/edgy-backports

« back to all changes in this revision

Viewing changes to builtin-ls-files.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2007-11-29 07:28:44 UTC
  • mfrom: (8.1.2 dapper-backports)
  • Revision ID: package-import@ubuntu.com-20071129072844-umsb7y3140yhxkth
Tags: 1:1.5.3.6-1.1~dapper1
* backport to dapper et al.
  - debian/rules changes to support source:Upstream-Version for old dpkg.
  - allow asciidoc (>7.0.2-3)

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *
6
6
 * Copyright (C) Linus Torvalds, 2005
7
7
 */
8
 
#include <fnmatch.h>
9
 
 
10
8
#include "cache.h"
11
9
#include "quote.h"
12
10
#include "dir.h"
13
11
#include "builtin.h"
 
12
#include "tree.h"
14
13
 
15
14
static int abbrev;
16
15
static int show_deleted;
28
27
static const char **pathspec;
29
28
static int error_unmatch;
30
29
static char *ps_matched;
 
30
static const char *with_tree;
31
31
 
32
32
static const char *tag_cached = "";
33
33
static const char *tag_unmerged = "";
91
91
static void show_other_files(struct dir_struct *dir)
92
92
{
93
93
        int i;
 
94
 
 
95
 
 
96
        /*
 
97
         * Skip matching and unmerged entries for the paths,
 
98
         * since we want just "others".
 
99
         *
 
100
         * (Matching entries are normally pruned during
 
101
         * the directory tree walk, but will show up for
 
102
         * gitlinks because we don't necessarily have
 
103
         * dir->show_other_directories set to suppress
 
104
         * them).
 
105
         */
94
106
        for (i = 0; i < dir->nr; i++) {
95
 
                /* We should not have a matching entry, but we
96
 
                 * may have an unmerged entry for this path.
97
 
                 */
98
107
                struct dir_entry *ent = dir->entries[i];
99
 
                int pos = cache_name_pos(ent->name, ent->len);
 
108
                int len, pos;
100
109
                struct cache_entry *ce;
 
110
 
 
111
                /*
 
112
                 * Remove the '/' at the end that directory
 
113
                 * walking adds for directory entries.
 
114
                 */
 
115
                len = ent->len;
 
116
                if (len && ent->name[len-1] == '/')
 
117
                        len--;
 
118
                pos = cache_name_pos(ent->name, len);
101
119
                if (0 <= pos)
102
 
                        die("bug in show-other-files");
 
120
                        continue;       /* exact match */
103
121
                pos = -pos - 1;
104
 
                if (pos < active_nr) { 
 
122
                if (pos < active_nr) {
105
123
                        ce = active_cache[pos];
106
 
                        if (ce_namelen(ce) == ent->len &&
107
 
                            !memcmp(ce->name, ent->name, ent->len))
 
124
                        if (ce_namelen(ce) == len &&
 
125
                            !memcmp(ce->name, ent->name, len))
108
126
                                continue; /* Yup, this one exists unmerged */
109
127
                }
110
128
                show_dir_entry(tag_other, ent);
218
236
 
219
237
                if (baselen)
220
238
                        path = base = prefix;
221
 
                read_directory(dir, path, base, baselen);
 
239
                read_directory(dir, path, base, baselen, pathspec);
222
240
                if (show_others)
223
241
                        show_other_files(dir);
224
242
                if (show_killed)
231
249
                                continue;
232
250
                        if (show_unmerged && !ce_stage(ce))
233
251
                                continue;
 
252
                        if (ce->ce_flags & htons(CE_UPDATE))
 
253
                                continue;
234
254
                        show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce);
235
255
                }
236
256
        }
260
280
 
261
281
        if (pos < 0)
262
282
                pos = -pos-1;
263
 
        active_cache += pos;
 
283
        memmove(active_cache, active_cache + pos,
 
284
                (active_nr - pos) * sizeof(struct cache_entry *));
264
285
        active_nr -= pos;
265
286
        first = 0;
266
287
        last = active_nr;
316
337
        return real_prefix;
317
338
}
318
339
 
 
340
/*
 
341
 * Read the tree specified with --with-tree option
 
342
 * (typically, HEAD) into stage #1 and then
 
343
 * squash them down to stage #0.  This is used for
 
344
 * --error-unmatch to list and check the path patterns
 
345
 * that were given from the command line.  We are not
 
346
 * going to write this index out.
 
347
 */
 
348
static void overlay_tree(const char *tree_name, const char *prefix)
 
349
{
 
350
        struct tree *tree;
 
351
        unsigned char sha1[20];
 
352
        const char **match;
 
353
        struct cache_entry *last_stage0 = NULL;
 
354
        int i;
 
355
 
 
356
        if (get_sha1(tree_name, sha1))
 
357
                die("tree-ish %s not found.", tree_name);
 
358
        tree = parse_tree_indirect(sha1);
 
359
        if (!tree)
 
360
                die("bad tree-ish %s", tree_name);
 
361
 
 
362
        /* Hoist the unmerged entries up to stage #3 to make room */
 
363
        for (i = 0; i < active_nr; i++) {
 
364
                struct cache_entry *ce = active_cache[i];
 
365
                if (!ce_stage(ce))
 
366
                        continue;
 
367
                ce->ce_flags |= htons(CE_STAGEMASK);
 
368
        }
 
369
 
 
370
        if (prefix) {
 
371
                static const char *(matchbuf[2]);
 
372
                matchbuf[0] = prefix;
 
373
                matchbuf [1] = NULL;
 
374
                match = matchbuf;
 
375
        } else
 
376
                match = NULL;
 
377
        if (read_tree(tree, 1, match))
 
378
                die("unable to read tree entries %s", tree_name);
 
379
 
 
380
        for (i = 0; i < active_nr; i++) {
 
381
                struct cache_entry *ce = active_cache[i];
 
382
                switch (ce_stage(ce)) {
 
383
                case 0:
 
384
                        last_stage0 = ce;
 
385
                        /* fallthru */
 
386
                default:
 
387
                        continue;
 
388
                case 1:
 
389
                        /*
 
390
                         * If there is stage #0 entry for this, we do not
 
391
                         * need to show it.  We use CE_UPDATE bit to mark
 
392
                         * such an entry.
 
393
                         */
 
394
                        if (last_stage0 &&
 
395
                            !strcmp(last_stage0->name, ce->name))
 
396
                                ce->ce_flags |= htons(CE_UPDATE);
 
397
                }
 
398
        }
 
399
}
 
400
 
319
401
static const char ls_files_usage[] =
320
402
        "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
321
403
        "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
325
407
int cmd_ls_files(int argc, const char **argv, const char *prefix)
326
408
{
327
409
        int i;
328
 
        int exc_given = 0;
 
410
        int exc_given = 0, require_work_tree = 0;
329
411
        struct dir_struct dir;
330
412
 
331
413
        memset(&dir, 0, sizeof(dir));
365
447
                }
366
448
                if (!strcmp(arg, "-m") || !strcmp(arg, "--modified")) {
367
449
                        show_modified = 1;
 
450
                        require_work_tree = 1;
368
451
                        continue;
369
452
                }
370
453
                if (!strcmp(arg, "-o") || !strcmp(arg, "--others")) {
371
454
                        show_others = 1;
 
455
                        require_work_tree = 1;
372
456
                        continue;
373
457
                }
374
458
                if (!strcmp(arg, "-i") || !strcmp(arg, "--ignored")) {
375
459
                        dir.show_ignored = 1;
 
460
                        require_work_tree = 1;
376
461
                        continue;
377
462
                }
378
463
                if (!strcmp(arg, "-s") || !strcmp(arg, "--stage")) {
381
466
                }
382
467
                if (!strcmp(arg, "-k") || !strcmp(arg, "--killed")) {
383
468
                        show_killed = 1;
 
469
                        require_work_tree = 1;
384
470
                        continue;
385
471
                }
386
472
                if (!strcmp(arg, "--directory")) {
404
490
                        add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]);
405
491
                        continue;
406
492
                }
407
 
                if (!strncmp(arg, "--exclude=", 10)) {
 
493
                if (!prefixcmp(arg, "--exclude=")) {
408
494
                        exc_given = 1;
409
495
                        add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]);
410
496
                        continue;
414
500
                        add_excludes_from_file(&dir, argv[++i]);
415
501
                        continue;
416
502
                }
417
 
                if (!strncmp(arg, "--exclude-from=", 15)) {
 
503
                if (!prefixcmp(arg, "--exclude-from=")) {
418
504
                        exc_given = 1;
419
505
                        add_excludes_from_file(&dir, arg+15);
420
506
                        continue;
421
507
                }
422
 
                if (!strncmp(arg, "--exclude-per-directory=", 24)) {
 
508
                if (!prefixcmp(arg, "--exclude-per-directory=")) {
423
509
                        exc_given = 1;
424
510
                        dir.exclude_per_dir = arg + 24;
425
511
                        continue;
432
518
                        error_unmatch = 1;
433
519
                        continue;
434
520
                }
435
 
                if (!strncmp(arg, "--abbrev=", 9)) {
 
521
                if (!prefixcmp(arg, "--with-tree=")) {
 
522
                        with_tree = arg + 12;
 
523
                        continue;
 
524
                }
 
525
                if (!prefixcmp(arg, "--abbrev=")) {
436
526
                        abbrev = strtoul(arg+9, NULL, 10);
437
527
                        if (abbrev && abbrev < MINIMUM_ABBREV)
438
528
                                abbrev = MINIMUM_ABBREV;
449
539
                break;
450
540
        }
451
541
 
 
542
        if (require_work_tree && !is_inside_work_tree()) {
 
543
                const char *work_tree = get_git_work_tree();
 
544
                if (!work_tree || chdir(work_tree))
 
545
                        die("This operation must be run in a work tree");
 
546
        }
 
547
 
452
548
        pathspec = get_pathspec(prefix, argv + i);
453
549
 
454
550
        /* Verify that the pathspec matches the prefix */
477
573
        read_cache();
478
574
        if (prefix)
479
575
                prune_cache(prefix);
 
576
        if (with_tree) {
 
577
                /*
 
578
                 * Basic sanity check; show-stages and show-unmerged
 
579
                 * would not make any sense with this option.
 
580
                 */
 
581
                if (show_stage || show_unmerged)
 
582
                        die("ls-files --with-tree is incompatible with -s or -u");
 
583
                overlay_tree(with_tree, prefix);
 
584
        }
480
585
        show_files(&dir, prefix);
481
586
 
482
587
        if (ps_matched) {
485
590
                 */
486
591
                int num, errors = 0;
487
592
                for (num = 0; pathspec[num]; num++) {
 
593
                        int other, found_dup;
 
594
 
488
595
                        if (ps_matched[num])
489
596
                                continue;
490
 
                        error("pathspec '%s' did not match any.",
 
597
                        /*
 
598
                         * The caller might have fed identical pathspec
 
599
                         * twice.  Do not barf on such a mistake.
 
600
                         */
 
601
                        for (found_dup = other = 0;
 
602
                             !found_dup && pathspec[other];
 
603
                             other++) {
 
604
                                if (other == num || !ps_matched[other])
 
605
                                        continue;
 
606
                                if (!strcmp(pathspec[other], pathspec[num]))
 
607
                                        /*
 
608
                                         * Ok, we have a match already.
 
609
                                         */
 
610
                                        found_dup = 1;
 
611
                        }
 
612
                        if (found_dup)
 
613
                                continue;
 
614
 
 
615
                        error("pathspec '%s' did not match any file(s) known to git.",
491
616
                              pathspec[num] + prefix_offset);
492
617
                        errors++;
493
618
                }
 
619
 
 
620
                if (errors)
 
621
                        fprintf(stderr, "Did you forget to 'git add'?\n");
 
622
 
494
623
                return errors ? 1 : 0;
495
624
        }
496
625