Merge branch 'jc/nostat'
authorJunio C Hamano <junkio@cox.net>
Wed, 22 Feb 2006 06:33:21 +0000 (22:33 -0800)
committerJunio C Hamano <junkio@cox.net>
Wed, 22 Feb 2006 06:33:21 +0000 (22:33 -0800)
* jc/nostat:
  cache_name_compare() compares name and stage, nothing else.
  "assume unchanged" git: documentation.
  ls-files: split "show-valid-bit" into a different option.
  "Assume unchanged" git: --really-refresh fix.
  ls-files: debugging aid for CE_VALID changes.
  "Assume unchanged" git: do not set CE_VALID with --refresh
  "Assume unchanged" git

1  2 
Documentation/git-ls-files.txt
apply.c
cache.h
diff-files.c
diff.c
ls-files.c

@@@ -8,13 -8,13 +8,14 @@@ git-ls-files - Information about files 
  
  SYNOPSIS
  --------
- 'git-ls-files' [-z] [-t]
+ [verse]
+ 'git-ls-files' [-z] [-t] [-v]
                (--[cached|deleted|others|ignored|stage|unmerged|killed|modified])\*
                (-[c|d|o|i|s|u|k|m])\*
                [-x <pattern>|--exclude=<pattern>]
                [-X <file>|--exclude-from=<file>]
                [--exclude-per-directory=<file>] 
 +              [--error-unmatch]
                [--full-name] [--] [<file>]\*
  
  DESCRIPTION
@@@ -73,10 -73,6 +74,10 @@@ OPTION
        read additional exclude patterns that apply only to the
        directory and its subdirectories in <file>.
  
 +--error-unmatch::
 +      If any <file> does not appear in the index, treat this as an
 +      error (return 1).
 +
  -t::
        Identify the file status with the following tags (followed by
        a space) at the start of each line:
        R::     removed/deleted
        C::     modified/changed
        K::     to be killed
 -      ?       other
 +      ?::     other
  
+ -v::
+       Similar to `-t`, but use lowercase letters for files
+       that are marked as 'always matching index'.
  --full-name::
        When run from a subdirectory, the command usually
        outputs paths relative to the current directory.  This
diff --combined apply.c
+++ b/apply.c
@@@ -1142,14 -1142,6 +1142,14 @@@ static int apply_one_fragment(struct bu
                size -= len;
        }
  
 +#ifdef NO_ACCURATE_DIFF
 +      if (oldsize > 0 && old[oldsize - 1] == '\n' &&
 +                      newsize > 0 && new[newsize - 1] == '\n') {
 +              oldsize--;
 +              newsize--;
 +      }
 +#endif
 +                      
        offset = find_offset(buf, desc->size, old, oldsize, frag->newpos);
        if (offset >= 0) {
                int diff = newsize - oldsize;
@@@ -1317,7 -1309,7 +1317,7 @@@ static int check_patch(struct patch *pa
                                        return -1;
                        }
  
-                       changed = ce_match_stat(active_cache[pos], &st);
+                       changed = ce_match_stat(active_cache[pos], &st, 1);
                        if (changed)
                                return error("%s: does not match index",
                                             old_name);
diff --combined cache.h
+++ b/cache.h
@@@ -91,6 -91,7 +91,7 @@@ struct cache_entry 
  #define CE_NAMEMASK  (0x0fff)
  #define CE_STAGEMASK (0x3000)
  #define CE_UPDATE    (0x4000)
+ #define CE_VALID     (0x8000)
  #define CE_STAGESHIFT 12
  
  #define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))
@@@ -144,8 -145,8 +145,8 @@@ extern int add_cache_entry(struct cache
  extern int remove_cache_entry_at(int pos);
  extern int remove_file_from_cache(const char *path);
  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
- extern int ce_match_stat(struct cache_entry *ce, struct stat *st);
- extern int ce_modified(struct cache_entry *ce, struct stat *st);
+ extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int);
+ extern int ce_modified(struct cache_entry *ce, struct stat *st, int);
  extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
  extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type);
  extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
@@@ -161,6 -162,7 +162,7 @@@ extern int commit_index_file(struct cac
  extern void rollback_index_file(struct cache_file *);
  
  extern int trust_executable_bit;
+ extern int assume_unchanged;
  extern int only_use_symrefs;
  extern int diff_rename_limit_default;
  extern int shared_repository;
@@@ -246,8 -248,8 +248,8 @@@ void datestamp(char *buf, int bufsize)
  unsigned long approxidate(const char *);
  
  extern int setup_ident(void);
 -extern const char *git_author_info(void);
 -extern const char *git_committer_info(void);
 +extern const char *git_author_info(int);
 +extern const char *git_committer_info(int);
  
  struct checkout {
        const char *base_dir;
@@@ -322,7 -324,7 +324,7 @@@ extern int num_packed_objects(const str
  extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*);
  extern int find_pack_entry_one(const unsigned char *, struct pack_entry *, struct packed_git *);
  extern void *unpack_entry_gently(struct pack_entry *, char *, unsigned long *);
 -extern void packed_object_info_detail(struct pack_entry *, char *, unsigned long *, unsigned long *, int *, unsigned char *);
 +extern void packed_object_info_detail(struct pack_entry *, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
  
  /* Dumb servers support */
  extern int update_server_info(int);
@@@ -348,6 -350,6 +350,6 @@@ extern int copy_fd(int ifd, int ofd)
  
  /* Finish off pack transfer receiving end */
  extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
 -extern int receive_keep_pack(int fd[2], const char *me);
 +extern int receive_keep_pack(int fd[2], const char *me, int quiet);
  
  #endif /* CACHE_H */
diff --combined diff-files.c
@@@ -88,8 -88,9 +88,8 @@@ int main(int argc, const char **argv
                }
                argv++; argc--;
        }
 -      if (combine_merges) {
 +      if (dense_combined_merges)
                diff_options.output_format = DIFF_FORMAT_PATCH;
 -      }
  
        /* Find the directory, and set up the pathspec */
        pathspec = get_pathspec(prefix, argv + 1);
                                               nce->sha1, 20);
                                        combine.p.parent[stage-2].mode =
                                                DIFF_FILE_CANON_MODE(mode);
 +                                      combine.p.parent[stage-2].status =
 +                                              DIFF_STATUS_MODIFIED;
                                }
  
                                /* diff against the proper unmerged stage */
                        if (combine_merges && num_compare_stages == 2) {
                                show_combined_diff(&combine.p, 2,
                                                   dense_combined_merges,
 -                                                 NULL);
 +                                                 NULL,
 +                                                 &diff_options);
                                free(combine.p.path);
                                continue;
                        }
                        show_file('-', ce);
                        continue;
                }
-               changed = ce_match_stat(ce, &st);
+               changed = ce_match_stat(ce, &st, 0);
                if (!changed && !diff_options.find_copies_harder)
                        continue;
                oldmode = ntohl(ce->ce_mode);
diff --combined diff.c
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -311,7 -311,7 +311,7 @@@ static int work_tree_matches(const cha
        ce = active_cache[pos];
        if ((lstat(name, &st) < 0) ||
            !S_ISREG(st.st_mode) || /* careful! */
-           ce_match_stat(ce, &st) ||
+           ce_match_stat(ce, &st, 0) ||
            memcmp(sha1, ce->sha1, 20))
                return 0;
        /* we return 1 only when we can stat, it is a regular file,
@@@ -963,7 -963,7 +963,7 @@@ void diff_free_filepair(struct diff_fil
  }
  
  /* This is different from find_unique_abbrev() in that
 - * it needs to deal with 0{40} SHA1.
 + * it stuffs the result with dots for alignment.
   */
  const char *diff_unique_abbrev(const unsigned char *sha1, int len)
  {
                return sha1_to_hex(sha1);
  
        abbrev = find_unique_abbrev(sha1, len);
 -      if (!abbrev) {
 -              if (!memcmp(sha1, null_sha1, 20)) {
 -                      char *buf = sha1_to_hex(null_sha1);
 -                      if (len < 37)
 -                              strcpy(buf + len, "...");
 -                      return buf;
 -              }
 -              else 
 -                      return sha1_to_hex(sha1);
 -      }
 +      if (!abbrev)
 +              return sha1_to_hex(sha1);
        abblen = strlen(abbrev);
        if (abblen < 37) {
                static char hex[41];
diff --combined ls-files.c
@@@ -20,13 -20,12 +20,14 @@@ static int show_unmerged = 0
  static int show_modified = 0;
  static int show_killed = 0;
  static int show_other_directories = 0;
+ static int show_valid_bit = 0;
  static int line_terminator = '\n';
  
  static int prefix_len = 0, prefix_offset = 0;
  static const char *prefix = NULL;
  static const char **pathspec = NULL;
 +static int error_unmatch = 0;
 +static char *ps_matched = NULL;
  
  static const char *tag_cached = "";
  static const char *tag_unmerged = "";
@@@ -327,8 -326,7 +328,8 @@@ static int cmp_name(const void *p1, con
   * Match a pathspec against a filename. The first "len" characters
   * are the common prefix
   */
 -static int match(const char **spec, const char *filename, int len)
 +static int match(const char **spec, char *ps_matched,
 +               const char *filename, int len)
  {
        const char *m;
  
                int matchlen = strlen(m + len);
  
                if (!matchlen)
 -                      return 1;
 +                      goto matched;
                if (!strncmp(m + len, filename + len, matchlen)) {
                        if (m[len + matchlen - 1] == '/')
 -                              return 1;
 +                              goto matched;
                        switch (filename[len + matchlen]) {
                        case '/': case '\0':
 -                              return 1;
 +                              goto matched;
                        }
                }
                if (!fnmatch(m + len, filename + len, 0))
 -                      return 1;
 +                      goto matched;
 +              if (ps_matched)
 +                      ps_matched++;
 +              continue;
 +      matched:
 +              if (ps_matched)
 +                      *ps_matched = 1;
 +              return 1;
        }
        return 0;
  }
@@@ -366,7 -357,7 +367,7 @@@ static void show_dir_entry(const char *
        if (len >= ent->len)
                die("git-ls-files: internal error - directory entry not superset of prefix");
  
 -      if (pathspec && !match(pathspec, ent->name, len))
 +      if (pathspec && !match(pathspec, ps_matched, ent->name, len))
                return;
  
        fputs(tag, stdout);
@@@ -454,9 -445,26 +455,26 @@@ static void show_ce_entry(const char *t
        if (len >= ce_namelen(ce))
                die("git-ls-files: internal error - cache entry not superset of prefix");
  
 -      if (pathspec && !match(pathspec, ce->name, len))
 +      if (pathspec && !match(pathspec, ps_matched, ce->name, len))
                return;
  
+       if (tag && *tag && show_valid_bit &&
+           (ce->ce_flags & htons(CE_VALID))) {
+               static char alttag[4];
+               memcpy(alttag, tag, 3);
+               if (isalpha(tag[0]))
+                       alttag[0] = tolower(tag[0]);
+               else if (tag[0] == '?')
+                       alttag[0] = '!';
+               else {
+                       alttag[0] = 'v';
+                       alttag[1] = tag[0];
+                       alttag[2] = ' ';
+                       alttag[3] = 0;
+               }
+               tag = alttag;
+       }
        if (!show_stage) {
                fputs(tag, stdout);
                write_name_quoted("", 0, ce->name + offset,
@@@ -484,28 -492,8 +502,28 @@@ static void show_files(void
                const char *path = ".", *base = "";
                int baselen = prefix_len;
  
 -              if (baselen)
 +              if (baselen) {
                        path = base = prefix;
 +                      if (exclude_per_dir) {
 +                              char *p, *pp = xmalloc(baselen+1);
 +                              memcpy(pp, prefix, baselen+1);
 +                              p = pp;
 +                              while (1) {
 +                                      char save = *p;
 +                                      *p = 0;
 +                                      push_exclude_per_directory(pp, p-pp);
 +                                      *p++ = save;
 +                                      if (!save)
 +                                              break;
 +                                      p = strchr(p, '/');
 +                                      if (p)
 +                                              p++;
 +                                      else
 +                                              p = pp + baselen;
 +                              }
 +                              free(pp);
 +                      }
 +              }
                read_directory(path, base, baselen);
                qsort(dir, nr_dir, sizeof(struct nond_on_fs *), cmp_name);
                if (show_others)
                        err = lstat(ce->name, &st);
                        if (show_deleted && err)
                                show_ce_entry(tag_removed, ce);
-                       if (show_modified && ce_modified(ce, &st))
+                       if (show_modified && ce_modified(ce, &st, 0))
                                show_ce_entry(tag_modified, ce);
                }
        }
@@@ -606,7 -594,7 +624,7 @@@ static void verify_pathspec(void
  }
  
  static const char ls_files_usage[] =
-       "git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
+       "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
        "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
        "[ --exclude-per-directory=<filename> ] [--full-name] [--] [<file>]*";
  
@@@ -631,13 -619,15 +649,15 @@@ int main(int argc, const char **argv
                        line_terminator = 0;
                        continue;
                }
-               if (!strcmp(arg, "-t")) {
+               if (!strcmp(arg, "-t") || !strcmp(arg, "-v")) {
                        tag_cached = "H ";
                        tag_unmerged = "M ";
                        tag_removed = "R ";
                        tag_modified = "C ";
                        tag_other = "? ";
                        tag_killed = "K ";
+                       if (arg[1] == 'v')
+                               show_valid_bit = 1;
                        continue;
                }
                if (!strcmp(arg, "-c") || !strcmp(arg, "--cached")) {
                        prefix_offset = 0;
                        continue;
                }
 +              if (!strcmp(arg, "--error-unmatch")) {
 +                      error_unmatch = 1;
 +                      continue;
 +              }
                if (*arg == '-')
                        usage(ls_files_usage);
                break;
        if (pathspec)
                verify_pathspec();
  
 +      /* Treat unmatching pathspec elements as errors */
 +      if (pathspec && error_unmatch) {
 +              int num;
 +              for (num = 0; pathspec[num]; num++)
 +                      ;
 +              ps_matched = xcalloc(1, num);
 +      }
 +
        if (show_ignored && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);
        if (prefix)
                prune_cache();
        show_files();
 +
 +      if (ps_matched) {
 +              /* We need to make sure all pathspec matched otherwise
 +               * it is an error.
 +               */
 +              int num, errors = 0;
 +              for (num = 0; pathspec[num]; num++) {
 +                      if (ps_matched[num])
 +                              continue;
 +                      error("pathspec '%s' did not match any.",
 +                            pathspec[num] + prefix_offset);
 +                      errors++;
 +              }
 +              return errors ? 1 : 0;
 +      }
 +
        return 0;
  }