2006-05-17 18:33:32 +02:00
|
|
|
/*
|
|
|
|
* "git add" builtin command
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006 Linus Torvalds
|
|
|
|
*/
|
|
|
|
#include "cache.h"
|
|
|
|
#include "builtin.h"
|
|
|
|
#include "dir.h"
|
git-add --interactive
A script to be driven when the user says "git add --interactive"
is introduced.
When it is run, first it runs its internal 'status' command to
show the current status, and then goes into its internactive
command loop.
The command loop shows the list of subcommands available, and
gives a prompt "What now> ". In general, when the prompt ends
with a single '>', you can pick only one of the choices given
and type return, like this:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
You also could say "s" or "sta" or "status" above as long as the
choice is unique.
The main command loop has 6 subcommands (plus help and quit).
* 'status' shows the change between HEAD and index (i.e. what
will be committed if you say "git commit"), and between index
and working tree files (i.e. what you could stage further
before "git commit" using "git-add") for each path. A sample
output looks like this:
staged unstaged path
1: binary nothing foo.png
2: +403/-35 +1/-1 git-add--interactive.perl
It shows that foo.png has differences from HEAD (but that is
binary so line count cannot be shown) and there is no
difference between indexed copy and the working tree
version (if the working tree version were also different,
'binary' would have been shown in place of 'nothing'). The
other file, git-add--interactive.perl, has 403 lines added
and 35 lines deleted if you commit what is in the index, but
working tree file has further modifications (one addition and
one deletion).
* 'update' shows the status information and gives prompt
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
2,3,4,5,7,9 from the list. You can say '*' to choose
everything.
What you chose are then highlighted with '*', like this:
staged unstaged path
1: binary nothing foo.png
* 2: +403/-35 +1/-1 git-add--interactive.perl
To remove selection, prefix the input with - like this:
Update>> -2
After making the selection, answer with an empty line to
stage the contents of working tree files for selected paths
in the index.
* 'revert' has a very similar UI to 'update', and the staged
information for selected paths are reverted to that of the
HEAD version. Reverting new paths makes them untracked.
* 'add untracked' has a very similar UI to 'update' and
'revert', and lets you add untracked paths to the index.
* 'patch' lets you choose one path out of 'status' like
selection. After choosing the path, it presents diff between
the index and the working tree file and asks you if you want
to stage the change of each hunk. You can say:
y - add the change from that hunk to index
n - do not add the change from that hunk to index
a - add the change from that hunk and all the rest to index
d - do not the change from that hunk nor any of the rest to index
j - do not decide on this hunk now, and view the next
undecided hunk
J - do not decide on this hunk now, and view the next hunk
k - do not decide on this hunk now, and view the previous
undecided hunk
K - do not decide on this hunk now, and view the previous hunk
After deciding the fate for all hunks, if there is any hunk
that was chosen, the index is updated with the selected hunks.
* 'diff' lets you review what will be committed (i.e. between
HEAD and index).
This is still rough, but does everything except a few things I
think are needed.
* 'patch' should be able to allow splitting a hunk into
multiple hunks.
* 'patch' does not adjust the line offsets @@ -k,l +m,n @@
in the hunk header. This does not have major problem in
practice, but it _should_ do the adjustment.
* It does not have any explicit support for a merge in
progress; it may not work at all.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-11 05:55:50 +01:00
|
|
|
#include "exec_cmd.h"
|
2006-05-20 10:28:49 +02:00
|
|
|
#include "cache-tree.h"
|
2007-04-20 10:39:39 +02:00
|
|
|
#include "diff.h"
|
|
|
|
#include "diffcore.h"
|
|
|
|
#include "commit.h"
|
|
|
|
#include "revision.h"
|
2007-09-18 02:06:44 +02:00
|
|
|
#include "run-command.h"
|
2007-10-03 23:45:02 +02:00
|
|
|
#include "parse-options.h"
|
2006-05-17 18:33:32 +02:00
|
|
|
|
2007-10-03 23:45:02 +02:00
|
|
|
static const char * const builtin_add_usage[] = {
|
|
|
|
"git-add [options] [--] <filepattern>...",
|
|
|
|
NULL
|
|
|
|
};
|
2006-05-17 18:33:32 +02:00
|
|
|
|
2007-05-12 08:42:00 +02:00
|
|
|
static int take_worktree_changes;
|
2007-02-28 04:31:10 +01:00
|
|
|
static const char *excludes_file;
|
|
|
|
|
2006-05-17 18:33:32 +02:00
|
|
|
static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
|
|
|
|
{
|
2006-05-17 22:23:19 +02:00
|
|
|
char *seen;
|
|
|
|
int i, specs;
|
2006-05-17 18:33:32 +02:00
|
|
|
struct dir_entry **src, **dst;
|
|
|
|
|
2006-05-17 22:23:19 +02:00
|
|
|
for (specs = 0; pathspec[specs]; specs++)
|
|
|
|
/* nothing */;
|
2006-07-25 09:30:18 +02:00
|
|
|
seen = xcalloc(specs, 1);
|
2006-05-17 22:23:19 +02:00
|
|
|
|
2006-05-17 18:33:32 +02:00
|
|
|
src = dst = dir->entries;
|
|
|
|
i = dir->nr;
|
|
|
|
while (--i >= 0) {
|
|
|
|
struct dir_entry *entry = *src++;
|
2006-12-29 20:01:31 +01:00
|
|
|
if (match_pathspec(pathspec, entry->name, entry->len,
|
|
|
|
prefix, seen))
|
|
|
|
*dst++ = entry;
|
2006-05-17 18:33:32 +02:00
|
|
|
}
|
|
|
|
dir->nr = dst - dir->entries;
|
2006-05-17 22:23:19 +02:00
|
|
|
|
|
|
|
for (i = 0; i < specs; i++) {
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
if (!seen[i] && !file_exists(pathspec[i]))
|
|
|
|
die("pathspec '%s' did not match any files",
|
|
|
|
pathspec[i]);
|
2006-05-17 22:23:19 +02:00
|
|
|
}
|
2007-10-29 08:00:33 +01:00
|
|
|
free(seen);
|
2006-05-17 18:33:32 +02:00
|
|
|
}
|
|
|
|
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
static void fill_directory(struct dir_struct *dir, const char **pathspec,
|
|
|
|
int ignored_too)
|
2006-05-17 18:33:32 +02:00
|
|
|
{
|
|
|
|
const char *path, *base;
|
|
|
|
int baselen;
|
|
|
|
|
|
|
|
/* Set up the default git porcelain excludes */
|
|
|
|
memset(dir, 0, sizeof(*dir));
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
if (!ignored_too) {
|
|
|
|
dir->collect_ignored = 1;
|
|
|
|
dir->exclude_per_dir = ".gitignore";
|
|
|
|
path = git_path("info/exclude");
|
|
|
|
if (!access(path, R_OK))
|
|
|
|
add_excludes_from_file(dir, path);
|
2007-07-28 20:26:35 +02:00
|
|
|
if (excludes_file != NULL && !access(excludes_file, R_OK))
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
add_excludes_from_file(dir, excludes_file);
|
|
|
|
}
|
2006-05-17 18:33:32 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate common prefix for the pathspec, and
|
|
|
|
* use that to optimize the directory walk
|
|
|
|
*/
|
|
|
|
baselen = common_prefix(pathspec);
|
|
|
|
path = ".";
|
|
|
|
base = "";
|
2007-09-16 00:32:36 +02:00
|
|
|
if (baselen)
|
|
|
|
path = base = xmemdupz(*pathspec, baselen);
|
2006-05-17 18:33:32 +02:00
|
|
|
|
|
|
|
/* Read the directory and prune it */
|
Optimize directory listing with pathspec limiter.
The way things are set up, you can now pass a "pathspec" to the
"read_directory()" function. If you pass NULL, it acts exactly
like it used to do (read everything). If you pass a non-NULL
pointer, it will simplify it into a "these are the prefixes
without any special characters", and stop any readdir() early if
the path in question doesn't match any of the prefixes.
NOTE! This does *not* obviate the need for the caller to do the *exact*
pathspec match later. It's a first-level filter on "read_directory()", but
it does not do the full pathspec thing. Maybe it should. But in the
meantime, builtin-add.c really does need to do first
read_directory(dir, .., pathspec);
if (pathspec)
prune_directory(dir, pathspec, baselen);
ie the "prune_directory()" part will do the *exact* pathspec pruning,
while the "read_directory()" will use the pathspec just to do some quick
high-level pruning of the directories it will recurse into.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-31 05:39:30 +02:00
|
|
|
read_directory(dir, path, base, baselen, pathspec);
|
2006-05-17 18:33:32 +02:00
|
|
|
if (pathspec)
|
|
|
|
prune_directory(dir, pathspec, baselen);
|
|
|
|
}
|
|
|
|
|
2007-04-20 10:39:39 +02:00
|
|
|
static void update_callback(struct diff_queue_struct *q,
|
|
|
|
struct diff_options *opt, void *cbdata)
|
|
|
|
{
|
|
|
|
int i, verbose;
|
|
|
|
|
|
|
|
verbose = *((int *)cbdata);
|
|
|
|
for (i = 0; i < q->nr; i++) {
|
|
|
|
struct diff_filepair *p = q->queue[i];
|
|
|
|
const char *path = p->one->path;
|
|
|
|
switch (p->status) {
|
|
|
|
default:
|
2007-09-14 10:29:04 +02:00
|
|
|
die("unexpected diff status %c", p->status);
|
2007-04-20 10:39:39 +02:00
|
|
|
case DIFF_STATUS_UNMERGED:
|
|
|
|
case DIFF_STATUS_MODIFIED:
|
2007-09-14 09:45:29 +02:00
|
|
|
case DIFF_STATUS_TYPE_CHANGED:
|
2007-04-20 10:39:39 +02:00
|
|
|
add_file_to_cache(path, verbose);
|
|
|
|
break;
|
|
|
|
case DIFF_STATUS_DELETED:
|
|
|
|
remove_file_from_cache(path);
|
|
|
|
if (verbose)
|
|
|
|
printf("remove '%s'\n", path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-18 02:06:44 +02:00
|
|
|
void add_files_to_cache(int verbose, const char *prefix, const char **files)
|
2007-04-20 10:39:39 +02:00
|
|
|
{
|
|
|
|
struct rev_info rev;
|
2007-08-15 19:01:43 +02:00
|
|
|
init_revisions(&rev, prefix);
|
2007-04-20 10:39:39 +02:00
|
|
|
setup_revisions(0, NULL, &rev, NULL);
|
2007-08-15 19:01:43 +02:00
|
|
|
rev.prune_data = get_pathspec(prefix, files);
|
2007-04-20 10:39:39 +02:00
|
|
|
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
|
|
|
|
rev.diffopt.format_callback = update_callback;
|
|
|
|
rev.diffopt.format_callback_data = &verbose;
|
|
|
|
run_diff_files(&rev, 0);
|
|
|
|
}
|
|
|
|
|
2007-08-11 23:59:01 +02:00
|
|
|
static void refresh(int verbose, const char **pathspec)
|
|
|
|
{
|
|
|
|
char *seen;
|
|
|
|
int i, specs;
|
|
|
|
|
|
|
|
for (specs = 0; pathspec[specs]; specs++)
|
|
|
|
/* nothing */;
|
|
|
|
seen = xcalloc(specs, 1);
|
|
|
|
if (read_cache() < 0)
|
|
|
|
die("index file corrupt");
|
|
|
|
refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen);
|
|
|
|
for (i = 0; i < specs; i++) {
|
|
|
|
if (!seen[i])
|
|
|
|
die("pathspec '%s' did not match any files", pathspec[i]);
|
|
|
|
}
|
2007-10-29 08:00:33 +01:00
|
|
|
free(seen);
|
2007-08-11 23:59:01 +02:00
|
|
|
}
|
|
|
|
|
2007-02-28 04:31:10 +01:00
|
|
|
static int git_add_config(const char *var, const char *value)
|
|
|
|
{
|
|
|
|
if (!strcmp(var, "core.excludesfile")) {
|
|
|
|
if (!value)
|
|
|
|
die("core.excludesfile without value");
|
|
|
|
excludes_file = xstrdup(value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return git_default_config(var, value);
|
|
|
|
}
|
|
|
|
|
2007-09-18 02:06:44 +02:00
|
|
|
int interactive_add(void)
|
|
|
|
{
|
|
|
|
const char *argv[2] = { "add--interactive", NULL };
|
|
|
|
|
|
|
|
return run_command_v_opt(argv, RUN_GIT_CMD);
|
|
|
|
}
|
|
|
|
|
2006-06-06 21:51:49 +02:00
|
|
|
static struct lock_file lock_file;
|
2006-05-17 18:33:32 +02:00
|
|
|
|
2007-08-29 00:41:23 +02:00
|
|
|
static const char ignore_error[] =
|
2006-12-26 02:46:38 +01:00
|
|
|
"The following paths are ignored by one of your .gitignore files:\n";
|
|
|
|
|
2007-10-03 23:45:02 +02:00
|
|
|
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
|
|
|
|
static int add_interactive = 0;
|
|
|
|
|
|
|
|
static struct option builtin_add_options[] = {
|
|
|
|
OPT__DRY_RUN(&show_only),
|
|
|
|
OPT__VERBOSE(&verbose),
|
|
|
|
OPT_GROUP(""),
|
|
|
|
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
|
|
|
|
OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"),
|
|
|
|
OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"),
|
|
|
|
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
|
|
|
|
OPT_END(),
|
|
|
|
};
|
|
|
|
|
2006-07-29 07:44:25 +02:00
|
|
|
int cmd_add(int argc, const char **argv, const char *prefix)
|
2006-05-17 18:33:32 +02:00
|
|
|
{
|
2007-10-03 23:45:02 +02:00
|
|
|
int i, newfd, orig_argc = argc;
|
2006-05-17 18:33:32 +02:00
|
|
|
const char **pathspec;
|
|
|
|
struct dir_struct dir;
|
git-add --interactive
A script to be driven when the user says "git add --interactive"
is introduced.
When it is run, first it runs its internal 'status' command to
show the current status, and then goes into its internactive
command loop.
The command loop shows the list of subcommands available, and
gives a prompt "What now> ". In general, when the prompt ends
with a single '>', you can pick only one of the choices given
and type return, like this:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
You also could say "s" or "sta" or "status" above as long as the
choice is unique.
The main command loop has 6 subcommands (plus help and quit).
* 'status' shows the change between HEAD and index (i.e. what
will be committed if you say "git commit"), and between index
and working tree files (i.e. what you could stage further
before "git commit" using "git-add") for each path. A sample
output looks like this:
staged unstaged path
1: binary nothing foo.png
2: +403/-35 +1/-1 git-add--interactive.perl
It shows that foo.png has differences from HEAD (but that is
binary so line count cannot be shown) and there is no
difference between indexed copy and the working tree
version (if the working tree version were also different,
'binary' would have been shown in place of 'nothing'). The
other file, git-add--interactive.perl, has 403 lines added
and 35 lines deleted if you commit what is in the index, but
working tree file has further modifications (one addition and
one deletion).
* 'update' shows the status information and gives prompt
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
2,3,4,5,7,9 from the list. You can say '*' to choose
everything.
What you chose are then highlighted with '*', like this:
staged unstaged path
1: binary nothing foo.png
* 2: +403/-35 +1/-1 git-add--interactive.perl
To remove selection, prefix the input with - like this:
Update>> -2
After making the selection, answer with an empty line to
stage the contents of working tree files for selected paths
in the index.
* 'revert' has a very similar UI to 'update', and the staged
information for selected paths are reverted to that of the
HEAD version. Reverting new paths makes them untracked.
* 'add untracked' has a very similar UI to 'update' and
'revert', and lets you add untracked paths to the index.
* 'patch' lets you choose one path out of 'status' like
selection. After choosing the path, it presents diff between
the index and the working tree file and asks you if you want
to stage the change of each hunk. You can say:
y - add the change from that hunk to index
n - do not add the change from that hunk to index
a - add the change from that hunk and all the rest to index
d - do not the change from that hunk nor any of the rest to index
j - do not decide on this hunk now, and view the next
undecided hunk
J - do not decide on this hunk now, and view the next hunk
k - do not decide on this hunk now, and view the previous
undecided hunk
K - do not decide on this hunk now, and view the previous hunk
After deciding the fate for all hunks, if there is any hunk
that was chosen, the index is updated with the selected hunks.
* 'diff' lets you review what will be committed (i.e. between
HEAD and index).
This is still rough, but does everything except a few things I
think are needed.
* 'patch' should be able to allow splitting a hunk into
multiple hunks.
* 'patch' does not adjust the line offsets @@ -k,l +m,n @@
in the hunk header. This does not have major problem in
practice, but it _should_ do the adjustment.
* It does not have any explicit support for a merge in
progress; it may not work at all.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-11 05:55:50 +01:00
|
|
|
|
2007-10-03 23:45:02 +02:00
|
|
|
argc = parse_options(argc, argv, builtin_add_options,
|
|
|
|
builtin_add_usage, 0);
|
git-add --interactive
A script to be driven when the user says "git add --interactive"
is introduced.
When it is run, first it runs its internal 'status' command to
show the current status, and then goes into its internactive
command loop.
The command loop shows the list of subcommands available, and
gives a prompt "What now> ". In general, when the prompt ends
with a single '>', you can pick only one of the choices given
and type return, like this:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
You also could say "s" or "sta" or "status" above as long as the
choice is unique.
The main command loop has 6 subcommands (plus help and quit).
* 'status' shows the change between HEAD and index (i.e. what
will be committed if you say "git commit"), and between index
and working tree files (i.e. what you could stage further
before "git commit" using "git-add") for each path. A sample
output looks like this:
staged unstaged path
1: binary nothing foo.png
2: +403/-35 +1/-1 git-add--interactive.perl
It shows that foo.png has differences from HEAD (but that is
binary so line count cannot be shown) and there is no
difference between indexed copy and the working tree
version (if the working tree version were also different,
'binary' would have been shown in place of 'nothing'). The
other file, git-add--interactive.perl, has 403 lines added
and 35 lines deleted if you commit what is in the index, but
working tree file has further modifications (one addition and
one deletion).
* 'update' shows the status information and gives prompt
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
2,3,4,5,7,9 from the list. You can say '*' to choose
everything.
What you chose are then highlighted with '*', like this:
staged unstaged path
1: binary nothing foo.png
* 2: +403/-35 +1/-1 git-add--interactive.perl
To remove selection, prefix the input with - like this:
Update>> -2
After making the selection, answer with an empty line to
stage the contents of working tree files for selected paths
in the index.
* 'revert' has a very similar UI to 'update', and the staged
information for selected paths are reverted to that of the
HEAD version. Reverting new paths makes them untracked.
* 'add untracked' has a very similar UI to 'update' and
'revert', and lets you add untracked paths to the index.
* 'patch' lets you choose one path out of 'status' like
selection. After choosing the path, it presents diff between
the index and the working tree file and asks you if you want
to stage the change of each hunk. You can say:
y - add the change from that hunk to index
n - do not add the change from that hunk to index
a - add the change from that hunk and all the rest to index
d - do not the change from that hunk nor any of the rest to index
j - do not decide on this hunk now, and view the next
undecided hunk
J - do not decide on this hunk now, and view the next hunk
k - do not decide on this hunk now, and view the previous
undecided hunk
K - do not decide on this hunk now, and view the previous hunk
After deciding the fate for all hunks, if there is any hunk
that was chosen, the index is updated with the selected hunks.
* 'diff' lets you review what will be committed (i.e. between
HEAD and index).
This is still rough, but does everything except a few things I
think are needed.
* 'patch' should be able to allow splitting a hunk into
multiple hunks.
* 'patch' does not adjust the line offsets @@ -k,l +m,n @@
in the hunk header. This does not have major problem in
practice, but it _should_ do the adjustment.
* It does not have any explicit support for a merge in
progress; it may not work at all.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-11 05:55:50 +01:00
|
|
|
if (add_interactive) {
|
2007-10-03 23:45:02 +02:00
|
|
|
if (add_interactive != 1 || orig_argc != 2)
|
git-add --interactive
A script to be driven when the user says "git add --interactive"
is introduced.
When it is run, first it runs its internal 'status' command to
show the current status, and then goes into its internactive
command loop.
The command loop shows the list of subcommands available, and
gives a prompt "What now> ". In general, when the prompt ends
with a single '>', you can pick only one of the choices given
and type return, like this:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
You also could say "s" or "sta" or "status" above as long as the
choice is unique.
The main command loop has 6 subcommands (plus help and quit).
* 'status' shows the change between HEAD and index (i.e. what
will be committed if you say "git commit"), and between index
and working tree files (i.e. what you could stage further
before "git commit" using "git-add") for each path. A sample
output looks like this:
staged unstaged path
1: binary nothing foo.png
2: +403/-35 +1/-1 git-add--interactive.perl
It shows that foo.png has differences from HEAD (but that is
binary so line count cannot be shown) and there is no
difference between indexed copy and the working tree
version (if the working tree version were also different,
'binary' would have been shown in place of 'nothing'). The
other file, git-add--interactive.perl, has 403 lines added
and 35 lines deleted if you commit what is in the index, but
working tree file has further modifications (one addition and
one deletion).
* 'update' shows the status information and gives prompt
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
2,3,4,5,7,9 from the list. You can say '*' to choose
everything.
What you chose are then highlighted with '*', like this:
staged unstaged path
1: binary nothing foo.png
* 2: +403/-35 +1/-1 git-add--interactive.perl
To remove selection, prefix the input with - like this:
Update>> -2
After making the selection, answer with an empty line to
stage the contents of working tree files for selected paths
in the index.
* 'revert' has a very similar UI to 'update', and the staged
information for selected paths are reverted to that of the
HEAD version. Reverting new paths makes them untracked.
* 'add untracked' has a very similar UI to 'update' and
'revert', and lets you add untracked paths to the index.
* 'patch' lets you choose one path out of 'status' like
selection. After choosing the path, it presents diff between
the index and the working tree file and asks you if you want
to stage the change of each hunk. You can say:
y - add the change from that hunk to index
n - do not add the change from that hunk to index
a - add the change from that hunk and all the rest to index
d - do not the change from that hunk nor any of the rest to index
j - do not decide on this hunk now, and view the next
undecided hunk
J - do not decide on this hunk now, and view the next hunk
k - do not decide on this hunk now, and view the previous
undecided hunk
K - do not decide on this hunk now, and view the previous hunk
After deciding the fate for all hunks, if there is any hunk
that was chosen, the index is updated with the selected hunks.
* 'diff' lets you review what will be committed (i.e. between
HEAD and index).
This is still rough, but does everything except a few things I
think are needed.
* 'patch' should be able to allow splitting a hunk into
multiple hunks.
* 'patch' does not adjust the line offsets @@ -k,l +m,n @@
in the hunk header. This does not have major problem in
practice, but it _should_ do the adjustment.
* It does not have any explicit support for a merge in
progress; it may not work at all.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-11 05:55:50 +01:00
|
|
|
die("add --interactive does not take any parameters");
|
2007-09-18 02:06:44 +02:00
|
|
|
exit(interactive_add());
|
git-add --interactive
A script to be driven when the user says "git add --interactive"
is introduced.
When it is run, first it runs its internal 'status' command to
show the current status, and then goes into its internactive
command loop.
The command loop shows the list of subcommands available, and
gives a prompt "What now> ". In general, when the prompt ends
with a single '>', you can pick only one of the choices given
and type return, like this:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
You also could say "s" or "sta" or "status" above as long as the
choice is unique.
The main command loop has 6 subcommands (plus help and quit).
* 'status' shows the change between HEAD and index (i.e. what
will be committed if you say "git commit"), and between index
and working tree files (i.e. what you could stage further
before "git commit" using "git-add") for each path. A sample
output looks like this:
staged unstaged path
1: binary nothing foo.png
2: +403/-35 +1/-1 git-add--interactive.perl
It shows that foo.png has differences from HEAD (but that is
binary so line count cannot be shown) and there is no
difference between indexed copy and the working tree
version (if the working tree version were also different,
'binary' would have been shown in place of 'nothing'). The
other file, git-add--interactive.perl, has 403 lines added
and 35 lines deleted if you commit what is in the index, but
working tree file has further modifications (one addition and
one deletion).
* 'update' shows the status information and gives prompt
"Update>>". When the prompt ends with double '>>', you can
make more than one selection, concatenated with whitespace or
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
2,3,4,5,7,9 from the list. You can say '*' to choose
everything.
What you chose are then highlighted with '*', like this:
staged unstaged path
1: binary nothing foo.png
* 2: +403/-35 +1/-1 git-add--interactive.perl
To remove selection, prefix the input with - like this:
Update>> -2
After making the selection, answer with an empty line to
stage the contents of working tree files for selected paths
in the index.
* 'revert' has a very similar UI to 'update', and the staged
information for selected paths are reverted to that of the
HEAD version. Reverting new paths makes them untracked.
* 'add untracked' has a very similar UI to 'update' and
'revert', and lets you add untracked paths to the index.
* 'patch' lets you choose one path out of 'status' like
selection. After choosing the path, it presents diff between
the index and the working tree file and asks you if you want
to stage the change of each hunk. You can say:
y - add the change from that hunk to index
n - do not add the change from that hunk to index
a - add the change from that hunk and all the rest to index
d - do not the change from that hunk nor any of the rest to index
j - do not decide on this hunk now, and view the next
undecided hunk
J - do not decide on this hunk now, and view the next hunk
k - do not decide on this hunk now, and view the previous
undecided hunk
K - do not decide on this hunk now, and view the previous hunk
After deciding the fate for all hunks, if there is any hunk
that was chosen, the index is updated with the selected hunks.
* 'diff' lets you review what will be committed (i.e. between
HEAD and index).
This is still rough, but does everything except a few things I
think are needed.
* 'patch' should be able to allow splitting a hunk into
multiple hunks.
* 'patch' does not adjust the line offsets @@ -k,l +m,n @@
in the hunk header. This does not have major problem in
practice, but it _should_ do the adjustment.
* It does not have any explicit support for a merge in
progress; it may not work at all.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-11 05:55:50 +01:00
|
|
|
}
|
2006-05-17 18:33:32 +02:00
|
|
|
|
2007-02-28 04:31:10 +01:00
|
|
|
git_config(git_add_config);
|
2006-05-17 18:33:32 +02:00
|
|
|
|
_GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index file.
When defined, this allows plumbing commands that update the
index (add, apply, checkout-index, merge-recursive, mv,
read-tree, rm, update-index, and write-tree) to write their
resulting index to an alternative index file while holding a
lock to the original index file. With this, git-commit that
jumps the index does not have to make an extra copy of the index
file, and more importantly, it can do the update while holding
the lock on the index.
However, I think the interface to let an environment variable
specify the output is a mistake, as shown in the documentation.
If a curious user has the environment variable set to something
other than the file GIT_INDEX_FILE points at, almost everything
will break. This should instead be a command line parameter to
tell these plumbing commands to write the result in the named
file, to prevent stupid mistakes.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-04-01 08:09:02 +02:00
|
|
|
newfd = hold_locked_index(&lock_file, 1);
|
2006-05-17 18:33:32 +02:00
|
|
|
|
2007-05-12 08:42:00 +02:00
|
|
|
if (take_worktree_changes) {
|
2007-09-18 02:06:44 +02:00
|
|
|
if (read_cache() < 0)
|
|
|
|
die("index file corrupt");
|
2007-11-03 00:42:23 +01:00
|
|
|
add_files_to_cache(verbose, prefix, argv);
|
2007-04-20 10:39:39 +02:00
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
|
2007-10-03 23:45:02 +02:00
|
|
|
if (argc == 0) {
|
2006-12-20 22:06:46 +01:00
|
|
|
fprintf(stderr, "Nothing specified, nothing added.\n");
|
|
|
|
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-03 23:45:02 +02:00
|
|
|
pathspec = get_pathspec(prefix, argv);
|
2006-05-17 18:33:32 +02:00
|
|
|
|
2007-08-11 23:59:01 +02:00
|
|
|
if (refresh_only) {
|
|
|
|
refresh(verbose, pathspec);
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
fill_directory(&dir, pathspec, ignored_too);
|
2006-05-17 18:33:32 +02:00
|
|
|
|
|
|
|
if (show_only) {
|
|
|
|
const char *sep = "", *eof = "";
|
|
|
|
for (i = 0; i < dir.nr; i++) {
|
|
|
|
printf("%s%s", sep, dir.entries[i]->name);
|
|
|
|
sep = " ";
|
|
|
|
eof = "\n";
|
|
|
|
}
|
|
|
|
fputs(eof, stdout);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-12-04 17:13:39 +01:00
|
|
|
if (read_cache() < 0)
|
|
|
|
die("index file corrupt");
|
|
|
|
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
if (dir.ignored_nr) {
|
2007-08-29 00:41:23 +02:00
|
|
|
fprintf(stderr, ignore_error);
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
for (i = 0; i < dir.ignored_nr; i++) {
|
|
|
|
fprintf(stderr, "%s\n", dir.ignored[i]->name);
|
2006-12-26 02:46:38 +01:00
|
|
|
}
|
builtin-add: simplify (and increase accuracy of) exclude handling
Previously, the code would always set up the excludes, and then manually
pick through the pathspec we were given, assuming that non-added but
existing paths were just ignored. This was mostly correct, but would
erroneously mark a totally empty directory as 'ignored'.
Instead, we now use the collect_ignored option of dir_struct, which
unambiguously tells us whether a path was ignored. This simplifies the
code, and means empty directories are now just not mentioned at all.
Furthermore, we now conditionally ask dir_struct to respect excludes,
depending on whether the '-f' flag has been set. This means we don't have
to pick through the result, checking for an 'ignored' flag; ignored entries
were either added or not in the first place.
We can safely get rid of the special 'ignored' flags to dir_entry, which
were not used anywhere else.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-06-12 23:42:14 +02:00
|
|
|
fprintf(stderr, "Use -f if you really want to add them.\n");
|
2007-08-29 00:41:23 +02:00
|
|
|
die("no files added");
|
2006-12-26 02:46:38 +01:00
|
|
|
}
|
|
|
|
|
2006-05-17 18:33:32 +02:00
|
|
|
for (i = 0; i < dir.nr; i++)
|
2007-04-02 07:14:40 +02:00
|
|
|
add_file_to_cache(dir.entries[i]->name, verbose);
|
2006-05-17 18:33:32 +02:00
|
|
|
|
2007-04-20 10:39:39 +02:00
|
|
|
finish:
|
2006-05-17 18:33:32 +02:00
|
|
|
if (active_cache_changed) {
|
|
|
|
if (write_cache(newfd, active_cache, active_nr) ||
|
_GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index file.
When defined, this allows plumbing commands that update the
index (add, apply, checkout-index, merge-recursive, mv,
read-tree, rm, update-index, and write-tree) to write their
resulting index to an alternative index file while holding a
lock to the original index file. With this, git-commit that
jumps the index does not have to make an extra copy of the index
file, and more importantly, it can do the update while holding
the lock on the index.
However, I think the interface to let an environment variable
specify the output is a mistake, as shown in the documentation.
If a curious user has the environment variable set to something
other than the file GIT_INDEX_FILE points at, almost everything
will break. This should instead be a command line parameter to
tell these plumbing commands to write the result in the named
file, to prevent stupid mistakes.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-04-01 08:09:02 +02:00
|
|
|
close(newfd) || commit_locked_index(&lock_file))
|
2006-05-17 18:33:32 +02:00
|
|
|
die("Unable to write new index file");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|