add: modify already added files when --chmod is given

When the chmod option was added to git add, it was hooked up to the diff
machinery, meaning that it only works when the version in the index
differs from the version on disk.

As the option was supposed to mirror the chmod option in update-index,
which always changes the mode in the index, regardless of the status of
the file, make sure the option behaves the same way in git add.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Thomas Gummerer
2016-09-14 22:07:47 +01:00
committed by Junio C Hamano
parent d9d7096662
commit 610d55af0f
6 changed files with 91 additions and 34 deletions

View File

@ -26,10 +26,25 @@ static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
struct update_callback_data {
int flags, force_mode;
int flags;
int add_errors;
};
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)
{
@ -65,8 +80,7 @@ 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, data->force_mode)) {
if (add_file_to_index(&the_index, path, data->flags)) {
if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
die(_("updating files failed"));
data->add_errors++;
@ -84,15 +98,14 @@ static void update_callback(struct diff_queue_struct *q,
}
}
int add_files_to_cache(const char *prefix, const struct pathspec *pathspec,
int flags, int force_mode)
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;
data.force_mode = force_mode;
init_revisions(&rev, prefix);
setup_revisions(0, NULL, &rev, NULL);
@ -281,7 +294,7 @@ static int add_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
static int add_files(struct dir_struct *dir, int flags, int force_mode)
static int add_files(struct dir_struct *dir, int flags)
{
int i, exit_status = 0;
@ -294,8 +307,7 @@ static int add_files(struct dir_struct *dir, int flags, int force_mode)
}
for (i = 0; i < dir->nr; i++)
if (add_file_to_index(&the_index, dir->entries[i]->name,
flags, force_mode)) {
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die(_("adding files failed"));
exit_status = 1;
@ -308,7 +320,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
int exit_status = 0;
struct pathspec pathspec;
struct dir_struct dir;
int flags, force_mode;
int flags;
int add_new_files;
int require_pathspec;
char *seen = NULL;
@ -342,13 +354,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (!show_only && ignore_missing)
die(_("Option --ignore-missing can only be used together with --dry-run"));
if (!chmod_arg)
force_mode = 0;
else if (!strcmp(chmod_arg, "-x"))
force_mode = 0666;
else if (!strcmp(chmod_arg, "+x"))
force_mode = 0777;
else
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;
@ -441,11 +448,13 @@ int cmd_add(int argc, const char **argv, const char *prefix)
plug_bulk_checkin();
exit_status |= add_files_to_cache(prefix, &pathspec, flags, force_mode);
exit_status |= add_files_to_cache(prefix, &pathspec, flags);
if (add_new_files)
exit_status |= add_files(&dir, flags, force_mode);
exit_status |= add_files(&dir, flags);
if (chmod_arg && pathspec.nr)
chmod_pathspec(&pathspec, chmod_arg[0]);
unplug_bulk_checkin();
finish: