l10n: git.pot: v2.11.0 round 2 (1 new, 1 removed)
[gitweb.git] / builtin / add.c
index fc7bf9f4cada189f82ca19246aa28bfb69af81e6..e8fb80b36e7386fa9a9da91a61893c14ec696be4 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "cache.h"
 #include "builtin.h"
+#include "lockfile.h"
 #include "dir.h"
 #include "pathspec.h"
 #include "exec_cmd.h"
 #include "diffcore.h"
 #include "revision.h"
 #include "bulk-checkin.h"
+#include "argv-array.h"
 
 static const char * const builtin_add_usage[] = {
-       N_("git add [options] [--] <pathspec>..."),
+       N_("git add [<options>] [--] <pathspec>..."),
        NULL
 };
 static int patch_interactive, add_interactive, edit_interactive;
@@ -26,10 +28,23 @@ static int take_worktree_changes;
 struct update_callback_data {
        int flags;
        int add_errors;
-       /* only needed for 2.0 transition preparation */
-       int warn_add_would_remove;
 };
 
+static void chmod_pathspec(struct pathspec *pathspec, int force_mode)
+{
+       int i;
+
+       for (i = 0; i < active_nr; i++) {
+               struct cache_entry *ce = active_cache[i];
+
+               if (pathspec && !ce_path_match(ce, pathspec, NULL))
+                       continue;
+
+               if (chmod_cache_entry(ce, force_mode) < 0)
+                       fprintf(stderr, "cannot chmod '%s'", ce->name);
+       }
+}
+
 static int fix_unmerged_status(struct diff_filepair *p,
                               struct update_callback_data *data)
 {
@@ -51,24 +66,6 @@ static int fix_unmerged_status(struct diff_filepair *p,
                return DIFF_STATUS_MODIFIED;
 }
 
-static const char *add_would_remove_warning = N_(
-       "You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
-"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
-"Paths like '%s' that are\n"
-"removed from your working tree are ignored with this version of Git.\n"
-"\n"
-"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
-"  ignores paths you removed from your working tree.\n"
-"\n"
-"* 'git add --all <pathspec>' will let you also record the removals.\n"
-"\n"
-"Run 'git status' to check the paths you removed from your working tree.\n");
-
-static void warn_add_would_remove(const char *path)
-{
-       warning(_(add_would_remove_warning), path);
-}
-
 static void update_callback(struct diff_queue_struct *q,
                            struct diff_options *opt, void *cbdata)
 {
@@ -83,17 +80,13 @@ static void update_callback(struct diff_queue_struct *q,
                        die(_("unexpected diff status %c"), p->status);
                case DIFF_STATUS_MODIFIED:
                case DIFF_STATUS_TYPE_CHANGED:
-                       if (add_file_to_index(&the_index, path, data->flags)) {
+                       if (add_file_to_index(&the_index, path, data->flags)) {
                                if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
                                        die(_("updating files failed"));
                                data->add_errors++;
                        }
                        break;
                case DIFF_STATUS_DELETED:
-                       if (data->warn_add_would_remove) {
-                               warn_add_would_remove(path);
-                               data->warn_add_would_remove = 0;
-                       }
                        if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
                                break;
                        if (!(data->flags & ADD_CACHE_PRETEND))
@@ -105,31 +98,24 @@ static void update_callback(struct diff_queue_struct *q,
        }
 }
 
-static void update_files_in_cache(const char *prefix,
-                                 const struct pathspec *pathspec,
-                                 struct update_callback_data *data)
+int add_files_to_cache(const char *prefix,
+                      const struct pathspec *pathspec, int flags)
 {
+       struct update_callback_data data;
        struct rev_info rev;
 
+       memset(&data, 0, sizeof(data));
+       data.flags = flags;
+
        init_revisions(&rev, prefix);
        setup_revisions(0, NULL, &rev, NULL);
        if (pathspec)
                copy_pathspec(&rev.prune_data, pathspec);
        rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
        rev.diffopt.format_callback = update_callback;
-       rev.diffopt.format_callback_data = data;
+       rev.diffopt.format_callback_data = &data;
        rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
        run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
-}
-
-int add_files_to_cache(const char *prefix,
-                      const struct pathspec *pathspec, int flags)
-{
-       struct update_callback_data data;
-
-       memset(&data, 0, sizeof(data));
-       data.flags = flags;
-       update_files_in_cache(prefix, pathspec, &data);
        return !!data.add_errors;
 }
 
@@ -172,23 +158,21 @@ static void refresh(int verbose, const struct pathspec *pathspec)
 int run_add_interactive(const char *revision, const char *patch_mode,
                        const struct pathspec *pathspec)
 {
-       int status, ac, i;
-       const char **args;
+       int status, i;
+       struct argv_array argv = ARGV_ARRAY_INIT;
 
-       args = xcalloc(sizeof(const char *), (pathspec->nr + 6));
-       ac = 0;
-       args[ac++] = "add--interactive";
+       argv_array_push(&argv, "add--interactive");
        if (patch_mode)
-               args[ac++] = patch_mode;
+               argv_array_push(&argv, patch_mode);
        if (revision)
-               args[ac++] = revision;
-       args[ac++] = "--";
+               argv_array_push(&argv, revision);
+       argv_array_push(&argv, "--");
        for (i = 0; i < pathspec->nr; i++)
                /* pass original pathspec, to be re-parsed */
-               args[ac++] = pathspec->items[i].original;
+               argv_array_push(&argv, pathspec->items[i].original);
 
-       status = run_command_v_opt(args, RUN_GIT_CMD);
-       free(args);
+       status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
+       argv_array_clear(&argv);
        return status;
 }
 
@@ -212,7 +196,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
        char *file = git_pathdup("ADD_EDIT.patch");
        const char *apply_argv[] = { "apply", "--recount", "--cached",
                NULL, NULL };
-       struct child_process child;
+       struct child_process child = CHILD_PROCESS_INIT;
        struct rev_info rev;
        int out;
        struct stat st;
@@ -239,14 +223,14 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
        if (run_diff_files(&rev, 0))
                die(_("Could not write patch"));
 
-       launch_editor(file, NULL, NULL);
+       if (launch_editor(file, NULL, NULL))
+               die(_("editing patch failed"));
 
        if (stat(file, &st))
                die_errno(_("Could not stat '%s'"), file);
        if (!st.st_size)
                die(_("Empty patch. Aborted."));
 
-       memset(&child, 0, sizeof(child));
        child.git_cmd = 1;
        child.argv = apply_argv;
        if (run_command(&child))
@@ -265,10 +249,12 @@ N_("The following paths are ignored by one of your .gitignore files:\n");
 static int verbose, show_only, ignored_too, refresh_only;
 static int ignore_add_errors, intent_to_add, ignore_missing;
 
-#define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */
+#define ADDREMOVE_DEFAULT 1
 static int addremove = ADDREMOVE_DEFAULT;
 static int addremove_explicit = -1; /* unspecified */
 
+static char *chmod_arg;
+
 static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
 {
        /* if we are told to ignore, we are not adding removals */
@@ -294,6 +280,7 @@ static struct option builtin_add_options[] = {
        OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
        OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
        OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
+       OPT_STRING( 0 , "chmod", &chmod_arg, N_("(+/-)x"), N_("override the executable bit of the listed files")),
        OPT_END(),
 };
 
@@ -316,11 +303,11 @@ static int add_files(struct dir_struct *dir, int flags)
                for (i = 0; i < dir->ignored_nr; i++)
                        fprintf(stderr, "%s\n", dir->ignored[i]->name);
                fprintf(stderr, _("Use -f if you really want to add them.\n"));
-               die(_("no files added"));
+               exit_status = 1;
        }
 
        for (i = 0; i < dir->nr; i++)
-               if (add_file_to_cache(dir->entries[i]->name, flags)) {
+               if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
                        if (!ignore_add_errors)
                                die(_("adding files failed"));
                        exit_status = 1;
@@ -331,14 +318,12 @@ static int add_files(struct dir_struct *dir, int flags)
 int cmd_add(int argc, const char **argv, const char *prefix)
 {
        int exit_status = 0;
-       int newfd;
        struct pathspec pathspec;
        struct dir_struct dir;
        int flags;
        int add_new_files;
        int require_pathspec;
        char *seen = NULL;
-       struct update_callback_data update_data;
 
        git_config(add_config, NULL);
 
@@ -362,34 +347,21 @@ int cmd_add(int argc, const char **argv, const char *prefix)
        if (addremove && take_worktree_changes)
                die(_("-A and -u are mutually incompatible"));
 
-       /*
-        * Warn when "git add pathspec..." was given without "-u" or "-A"
-        * and pathspec... covers a removed path.
-        */
-       memset(&update_data, 0, sizeof(update_data));
-       if (!take_worktree_changes && addremove_explicit < 0)
-               update_data.warn_add_would_remove = 1;
-
        if (!take_worktree_changes && addremove_explicit < 0 && argc)
-               /*
-                * Turn "git add pathspec..." to "git add -A pathspec..."
-                * in Git 2.0 but not yet
-                */
-               ; /* addremove = 1; */
+               /* Turn "git add pathspec..." to "git add -A pathspec..." */
+               addremove = 1;
 
        if (!show_only && ignore_missing)
                die(_("Option --ignore-missing can only be used together with --dry-run"));
 
-       if ((addremove || take_worktree_changes) && !argc) {
-               static const char *whole[2] = { ":/", NULL };
-               argc = 1;
-               argv = whole;
-       }
+       if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
+                         chmod_arg[1] != 'x' || chmod_arg[2]))
+               die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
 
        add_new_files = !take_worktree_changes && !refresh_only;
-       require_pathspec = !take_worktree_changes;
+       require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
 
-       newfd = hold_locked_index(&lock_file, 1);
+       hold_locked_index(&lock_file, 1);
 
        flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
                 (show_only ? ADD_CACHE_PRETEND : 0) |
@@ -476,19 +448,18 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
        plug_bulk_checkin();
 
-       update_data.flags = flags;
-       update_files_in_cache(prefix, &pathspec, &update_data);
+       exit_status |= add_files_to_cache(prefix, &pathspec, flags);
 
-       exit_status |= !!update_data.add_errors;
        if (add_new_files)
                exit_status |= add_files(&dir, flags);
 
+       if (chmod_arg && pathspec.nr)
+               chmod_pathspec(&pathspec, chmod_arg[0]);
        unplug_bulk_checkin();
 
 finish:
        if (active_cache_changed) {
-               if (write_cache(newfd, active_cache, active_nr) ||
-                   commit_locked_index(&lock_file))
+               if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
                        die(_("Unable to write new index file"));
        }