Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Tue, 12 Feb 2013 20:23:12 +0000 (12:23 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 12 Feb 2013 20:23:12 +0000 (12:23 -0800)
* maint:
Replace filepattern with pathspec for consistency

1  2 
Documentation/git-add.txt
builtin/add.c
builtin/commit.c
index 533355984cf00bc81f21dfeee4a4e8977631f423,d0cdb07844b8361debc1565f11b11b813fe81c57..d980e2cb7d3d7281e2cffc1950a1ba31fa06e06e
@@@ -11,7 -11,7 +11,7 @@@ SYNOPSI
  'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
          [--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
          [--refresh] [--ignore-errors] [--ignore-missing] [--]
-         [<filepattern>...]
+         [<pathspec>...]
  
  DESCRIPTION
  -----------
@@@ -49,7 -49,7 +49,7 @@@ commit
  
  OPTIONS
  -------
- <filepattern>...::
+ <pathspec>...::
        Files to add content from.  Fileglobs (e.g. `*.c`) can
        be given to add all matching files.  Also a
        leading directory name (e.g. `dir` to add `dir/file1`
@@@ -100,21 -100,20 +100,21 @@@ apply to the index. See EDITING PATCHE
  
  -u::
  --update::
-       Only match <filepattern> against already tracked files in
+       Only match <pathspec> against already tracked files in
        the index rather than the working tree. That means that it
        will never stage new files, but that it will stage modified
        new contents of tracked files and that it will remove files
        from the index if the corresponding files in the working tree
        have been removed.
  +
- If no <filepattern> is given, the current version of Git defaults to
 -If no <pathspec> is given, default to "."; in other words,
 -update all tracked files in the current directory and its
 -subdirectories.
++If no <pathspec> is given, the current version of Git defaults to
 +"."; in other words, update all tracked files in the current directory
 +and its subdirectories. This default will change in a future version
 +of Git, hence the form without <filepattern> should not be used.
  
  -A::
  --all::
-       Like `-u`, but match <filepattern> against files in the
+       Like `-u`, but match <pathspec> against files in the
        working tree in addition to the index. That means that it
        will find new files as well as staging modified content and
        removing files that are no longer in the working tree.
diff --combined builtin/add.c
index 7738025a2e56ea3fbd256666998040981360e5ab,632594768d9ee7d723a35377ab4cff9cf714a0d9..0dd014eb96110e46e79fd6bad0bab843551fab79
@@@ -6,7 -6,6 +6,7 @@@
  #include "cache.h"
  #include "builtin.h"
  #include "dir.h"
 +#include "pathspec.h"
  #include "exec_cmd.h"
  #include "cache-tree.h"
  #include "run-command.h"
@@@ -17,7 -16,7 +17,7 @@@
  #include "bulk-checkin.h"
  
  static const char * const builtin_add_usage[] = {
-       N_("git add [options] [--] <filepattern>..."),
+       N_("git add [options] [--] <pathspec>..."),
        NULL
  };
  static int patch_interactive, add_interactive, edit_interactive;
@@@ -98,6 -97,39 +98,6 @@@ int add_files_to_cache(const char *pref
        return !!data.add_errors;
  }
  
 -static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
 -{
 -      int num_unmatched = 0, i;
 -
 -      /*
 -       * Since we are walking the index as if we were walking the directory,
 -       * we have to mark the matched pathspec as seen; otherwise we will
 -       * mistakenly think that the user gave a pathspec that did not match
 -       * anything.
 -       */
 -      for (i = 0; i < specs; i++)
 -              if (!seen[i])
 -                      num_unmatched++;
 -      if (!num_unmatched)
 -              return;
 -      for (i = 0; i < active_nr; i++) {
 -              struct cache_entry *ce = active_cache[i];
 -              match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen);
 -      }
 -}
 -
 -static char *find_used_pathspec(const char **pathspec)
 -{
 -      char *seen;
 -      int i;
 -
 -      for (i = 0; pathspec[i];  i++)
 -              ; /* just counting */
 -      seen = xcalloc(i, 1);
 -      fill_pathspec_matches(pathspec, seen, i);
 -      return seen;
 -}
 -
  static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
  {
        char *seen;
                        *dst++ = entry;
        }
        dir->nr = dst - dir->entries;
 -      fill_pathspec_matches(pathspec, seen, specs);
 +      add_pathspec_matches_against_index(pathspec, seen, specs);
        return seen;
  }
  
 +/*
 + * Checks the index to see whether any path in pathspec refers to
 + * something inside a submodule.  If so, dies with an error message.
 + */
  static void treat_gitlinks(const char **pathspec)
  {
        int i;
        if (!pathspec || !*pathspec)
                return;
  
 -      for (i = 0; i < active_nr; i++) {
 -              struct cache_entry *ce = active_cache[i];
 -              if (S_ISGITLINK(ce->ce_mode)) {
 -                      int len = ce_namelen(ce), j;
 -                      for (j = 0; pathspec[j]; j++) {
 -                              int len2 = strlen(pathspec[j]);
 -                              if (len2 <= len || pathspec[j][len] != '/' ||
 -                                  memcmp(ce->name, pathspec[j], len))
 -                                      continue;
 -                              if (len2 == len + 1)
 -                                      /* strip trailing slash */
 -                                      pathspec[j] = xstrndup(ce->name, len);
 -                              else
 -                                      die (_("Path '%s' is in submodule '%.*s'"),
 -                                              pathspec[j], len, ce->name);
 -                      }
 -              }
 -      }
 +      for (i = 0; pathspec[i]; i++)
 +              pathspec[i] = check_path_for_gitlink(pathspec[i]);
  }
  
  static void refresh(int verbose, const char **pathspec)
          free(seen);
  }
  
 -static const char **validate_pathspec(int argc, const char **argv, const char *prefix)
 +/*
 + * Normalizes argv relative to prefix, via get_pathspec(), and then
 + * runs die_if_path_beyond_symlink() on each path in the normalized
 + * list.
 + */
 +static const char **validate_pathspec(const char **argv, const char *prefix)
  {
        const char **pathspec = get_pathspec(prefix, argv);
  
        if (pathspec) {
                const char **p;
                for (p = pathspec; *p; p++) {
 -                      if (has_symlink_leading_path(*p, strlen(*p))) {
 -                              int len = prefix ? strlen(prefix) : 0;
 -                              die(_("'%s' is beyond a symbolic link"), *p + len);
 -                      }
 +                      die_if_path_beyond_symlink(*p, prefix);
                }
        }
  
@@@ -206,7 -248,7 +206,7 @@@ int interactive_add(int argc, const cha
        const char **pathspec = NULL;
  
        if (argc) {
 -              pathspec = validate_pathspec(argc, argv, prefix);
 +              pathspec = validate_pathspec(argv, prefix);
                if (!pathspec)
                        return -1;
        }
@@@ -321,35 -363,6 +321,35 @@@ static int add_files(struct dir_struct 
        return exit_status;
  }
  
 +static void warn_pathless_add(const char *option_name, const char *short_name) {
 +      /*
 +       * To be consistent with "git add -p" and most Git
 +       * commands, we should default to being tree-wide, but
 +       * this is not the original behavior and can't be
 +       * changed until users trained themselves not to type
 +       * "git add -u" or "git add -A". For now, we warn and
 +       * keep the old behavior. Later, this warning can be
 +       * turned into a die(...), and eventually we may
 +       * reallow the command with a new behavior.
 +       */
 +      warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
 +                "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
 +                "To add content for the whole tree, run:\n"
 +                "\n"
 +                "  git add %s :/\n"
 +                "  (or git add %s :/)\n"
 +                "\n"
 +                "To restrict the command to the current directory, run:\n"
 +                "\n"
 +                "  git add %s .\n"
 +                "  (or git add %s .)\n"
 +                "\n"
 +                "With the current Git version, the command is restricted to the current directory."),
 +              option_name, short_name,
 +              option_name, short_name,
 +              option_name, short_name);
 +}
 +
  int cmd_add(int argc, const char **argv, const char *prefix)
  {
        int exit_status = 0;
        int add_new_files;
        int require_pathspec;
        char *seen = NULL;
 +      const char *option_with_implicit_dot = NULL;
 +      const char *short_option_with_implicit_dot = NULL;
  
        git_config(add_config, NULL);
  
                die(_("-A and -u are mutually incompatible"));
        if (!show_only && ignore_missing)
                die(_("Option --ignore-missing can only be used together with --dry-run"));
 -      if ((addremove || take_worktree_changes) && !argc) {
 +      if (addremove) {
 +              option_with_implicit_dot = "--all";
 +              short_option_with_implicit_dot = "-A";
 +      }
 +      if (take_worktree_changes) {
 +              option_with_implicit_dot = "--update";
 +              short_option_with_implicit_dot = "-u";
 +      }
 +      if (option_with_implicit_dot && !argc) {
                static const char *here[2] = { ".", NULL };
 +              if (prefix)
 +                      warn_pathless_add(option_with_implicit_dot,
 +                                        short_option_with_implicit_dot);
                argc = 1;
                argv = here;
        }
                fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
                return 0;
        }
 -      pathspec = validate_pathspec(argc, argv, prefix);
 +      pathspec = validate_pathspec(argv, prefix);
  
        if (read_cache() < 0)
                die(_("index file corrupt"));
  
                path_exclude_check_init(&check, &dir);
                if (!seen)
 -                      seen = find_used_pathspec(pathspec);
 +                      seen = find_pathspecs_matching_against_index(pathspec);
                for (i = 0; pathspec[i]; i++) {
                        if (!seen[i] && pathspec[i][0]
                            && !file_exists(pathspec[i])) {
                                if (ignore_missing) {
                                        int dtype = DT_UNKNOWN;
 -                                      if (path_excluded(&check, pathspec[i], -1, &dtype))
 +                                      if (is_path_excluded(&check, pathspec[i], -1, &dtype))
                                                dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
                                } else
                                        die(_("pathspec '%s' did not match any files"),
diff --combined builtin/commit.c
index 1a0e5f14a36975a012199f9e7a96d9a58ee986d0,96684108e7437537536c42fafa7a84ddef848520..3348aa14e9d5a76fa06e43625c5d74cb047accb6
  #include "sequencer.h"
  
  static const char * const builtin_commit_usage[] = {
-       N_("git commit [options] [--] <filepattern>..."),
+       N_("git commit [options] [--] <pathspec>..."),
        NULL
  };
  
  static const char * const builtin_status_usage[] = {
-       N_("git status [options] [--] <filepattern>..."),
+       N_("git status [options] [--] <pathspec>..."),
        NULL
  };
  
@@@ -103,7 -103,7 +103,7 @@@ static enum 
        CLEANUP_NONE,
        CLEANUP_ALL
  } cleanup_mode;
 -static char *cleanup_arg;
 +static const char *cleanup_arg;
  
  static enum commit_whence whence;
  static int use_editor = 1, include_status = 1;
@@@ -733,15 -733,15 +733,15 @@@ static int prepare_to_commit(const cha
                if (cleanup_mode == CLEANUP_ALL)
                        status_printf(s, GIT_COLOR_NORMAL,
                                _("Please enter the commit message for your changes."
 -                              " Lines starting\nwith '#' will be ignored, and an empty"
 -                              " message aborts the commit.\n"));
 +                                " Lines starting\nwith '%c' will be ignored, and an empty"
 +                                " message aborts the commit.\n"), comment_line_char);
                else /* CLEANUP_SPACE, that is. */
                        status_printf(s, GIT_COLOR_NORMAL,
                                _("Please enter the commit message for your changes."
 -                              " Lines starting\n"
 -                              "with '#' will be kept; you may remove them"
 -                              " yourself if you want to.\n"
 -                              "An empty message aborts the commit.\n"));
 +                                " Lines starting\n"
 +                                "with '%c' will be kept; you may remove them"
 +                                " yourself if you want to.\n"
 +                                "An empty message aborts the commit.\n"), comment_line_char);
                if (only_include_assumed)
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                                        "%s", only_include_assumed);
@@@ -946,14 -946,24 +946,14 @@@ static void handle_untracked_files_arg(
  
  static const char *read_commit_message(const char *name)
  {
 -      const char *out_enc, *out;
 +      const char *out_enc;
        struct commit *commit;
  
        commit = lookup_commit_reference_by_name(name);
        if (!commit)
                die(_("could not lookup commit %s"), name);
        out_enc = get_commit_output_encoding();
 -      out = logmsg_reencode(commit, out_enc);
 -
 -      /*
 -       * If we failed to reencode the buffer, just copy it
 -       * byte for byte so the user can try to fix it up.
 -       * This also handles the case where input and output
 -       * encodings are identical.
 -       */
 -      if (out == NULL)
 -              out = xstrdup(commit->buffer);
 -      return out;
 +      return logmsg_reencode(commit, out_enc);
  }
  
  static int parse_and_validate_options(int argc, const char *argv[],
@@@ -1310,8 -1320,6 +1310,8 @@@ static int git_commit_config(const cha
                include_status = git_config_bool(k, v);
                return 0;
        }
 +      if (!strcmp(k, "commit.cleanup"))
 +              return git_config_string(&cleanup_arg, k, v);
  
        status = git_gpg_config(k, v, NULL);
        if (status)
        return git_status_config(k, v, s);
  }
  
 -static const char post_rewrite_hook[] = "hooks/post-rewrite";
 -
  static int run_rewrite_hook(const unsigned char *oldsha1,
                            const unsigned char *newsha1)
  {
        int code;
        size_t n;
  
 -      if (access(git_path(post_rewrite_hook), X_OK) < 0)
 +      argv[0] = find_hook("post-rewrite");
 +      if (!argv[0])
                return 0;
  
 -      argv[0] = git_path(post_rewrite_hook);
        argv[1] = "amend";
        argv[2] = NULL;