add: add --chmod=+x / --chmod=-x options
The executable bit will not be detected (and therefore will not be set) for paths in a repository with `core.filemode` set to false, though the users may still wish to add files as executable for compatibility with other users who _do_ have `core.filemode` functionality. For example, Windows users adding shell scripts may wish to add them as executable for compatibility with users on non-Windows. Although this can be done with a plumbing command (`git update-index --add --chmod=+x foo`), teaching the `git-add` command allows users to set a file executable with a command that they're already familiar with. Signed-off-by: Edward Thomson <ethomson@edwardthomson.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
60bd4b1c51
commit
4e55ed32db
@ -26,7 +26,7 @@ static int patch_interactive, add_interactive, edit_interactive;
|
||||
static int take_worktree_changes;
|
||||
|
||||
struct update_callback_data {
|
||||
int flags;
|
||||
int flags, force_mode;
|
||||
int add_errors;
|
||||
};
|
||||
|
||||
@ -65,7 +65,8 @@ 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, data->force_mode)) {
|
||||
if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
|
||||
die(_("updating files failed"));
|
||||
data->add_errors++;
|
||||
@ -83,14 +84,15 @@ static void update_callback(struct diff_queue_struct *q,
|
||||
}
|
||||
}
|
||||
|
||||
int add_files_to_cache(const char *prefix,
|
||||
const struct pathspec *pathspec, int flags)
|
||||
int add_files_to_cache(const char *prefix, const struct pathspec *pathspec,
|
||||
int flags, int force_mode)
|
||||
{
|
||||
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);
|
||||
@ -238,6 +240,8 @@ static int ignore_add_errors, intent_to_add, ignore_missing;
|
||||
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 */
|
||||
@ -263,6 +267,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(),
|
||||
};
|
||||
|
||||
@ -276,7 +281,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)
|
||||
static int add_files(struct dir_struct *dir, int flags, int force_mode)
|
||||
{
|
||||
int i, exit_status = 0;
|
||||
|
||||
@ -289,7 +294,8 @@ static int add_files(struct dir_struct *dir, int flags)
|
||||
}
|
||||
|
||||
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, force_mode)) {
|
||||
if (!ignore_add_errors)
|
||||
die(_("adding files failed"));
|
||||
exit_status = 1;
|
||||
@ -302,7 +308,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;
|
||||
int flags, force_mode;
|
||||
int add_new_files;
|
||||
int require_pathspec;
|
||||
char *seen = NULL;
|
||||
@ -336,6 +342,15 @@ 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
|
||||
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 || (0 < addremove_explicit));
|
||||
|
||||
@ -426,10 +441,10 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
|
||||
plug_bulk_checkin();
|
||||
|
||||
exit_status |= add_files_to_cache(prefix, &pathspec, flags);
|
||||
exit_status |= add_files_to_cache(prefix, &pathspec, flags, force_mode);
|
||||
|
||||
if (add_new_files)
|
||||
exit_status |= add_files(&dir, flags);
|
||||
exit_status |= add_files(&dir, flags, force_mode);
|
||||
|
||||
unplug_bulk_checkin();
|
||||
|
||||
|
Reference in New Issue
Block a user