2006-05-18 00:33:32 +08:00
|
|
|
/*
|
|
|
|
* "git add" builtin command
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006 Linus Torvalds
|
|
|
|
*/
|
2019-01-24 16:29:12 +08:00
|
|
|
#define USE_THE_INDEX_COMPATIBILITY_MACROS
|
2006-05-18 00:33:32 +08:00
|
|
|
#include "cache.h"
|
2017-06-15 02:07:36 +08:00
|
|
|
#include "config.h"
|
2006-05-18 00:33:32 +08:00
|
|
|
#include "builtin.h"
|
2014-10-01 18:28:42 +08:00
|
|
|
#include "lockfile.h"
|
2006-05-18 00:33:32 +08:00
|
|
|
#include "dir.h"
|
2013-01-07 00:58:08 +08:00
|
|
|
#include "pathspec.h"
|
2018-04-11 05:26:18 +08:00
|
|
|
#include "exec-cmd.h"
|
2006-05-20 16:28:49 +08:00
|
|
|
#include "cache-tree.h"
|
2007-09-18 08:06:44 +08:00
|
|
|
#include "run-command.h"
|
2007-10-04 05:45:02 +08:00
|
|
|
#include "parse-options.h"
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
#include "diff.h"
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
#include "diffcore.h"
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
#include "revision.h"
|
2011-10-29 05:48:40 +08:00
|
|
|
#include "bulk-checkin.h"
|
2014-03-15 19:14:40 +08:00
|
|
|
#include "argv-array.h"
|
2017-05-10 03:17:59 +08:00
|
|
|
#include "submodule.h"
|
2006-05-18 00:33:32 +08:00
|
|
|
|
2007-10-04 05:45:02 +08:00
|
|
|
static const char * const builtin_add_usage[] = {
|
2015-01-13 15:44:47 +08:00
|
|
|
N_("git add [<options>] [--] <pathspec>..."),
|
2007-10-04 05:45:02 +08:00
|
|
|
NULL
|
|
|
|
};
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
static int patch_interactive, add_interactive, edit_interactive;
|
2007-05-12 14:42:00 +08:00
|
|
|
static int take_worktree_changes;
|
2017-11-17 00:38:28 +08:00
|
|
|
static int add_renormalize;
|
2007-02-28 11:31:10 +08:00
|
|
|
|
2011-03-16 15:08:34 +08:00
|
|
|
struct update_callback_data {
|
2016-09-15 05:07:47 +08:00
|
|
|
int flags;
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
int add_errors;
|
|
|
|
};
|
|
|
|
|
2017-08-09 08:51:23 +08:00
|
|
|
static void chmod_pathspec(struct pathspec *pathspec, char flip)
|
2016-09-15 05:07:47 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < active_nr; i++) {
|
|
|
|
struct cache_entry *ce = active_cache[i];
|
|
|
|
|
2018-08-14 00:14:22 +08:00
|
|
|
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
|
2016-09-15 05:07:47 +08:00
|
|
|
continue;
|
|
|
|
|
2017-08-09 08:51:23 +08:00
|
|
|
if (chmod_cache_entry(ce, flip) < 0)
|
|
|
|
fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
|
2016-09-15 05:07:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-21 09:11:19 +08:00
|
|
|
static int fix_unmerged_status(struct diff_filepair *p,
|
|
|
|
struct update_callback_data *data)
|
|
|
|
{
|
|
|
|
if (p->status != DIFF_STATUS_UNMERGED)
|
|
|
|
return p->status;
|
|
|
|
if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
|
|
|
|
/*
|
|
|
|
* This is not an explicit add request, and the
|
|
|
|
* path is missing from the working tree (deleted)
|
|
|
|
*/
|
|
|
|
return DIFF_STATUS_DELETED;
|
|
|
|
else
|
|
|
|
/*
|
|
|
|
* Either an explicit add request, or path exists
|
|
|
|
* in the working tree. An attempt to explicitly
|
|
|
|
* add a path that does not exist in the working tree
|
|
|
|
* will be caught as an error by the caller immediately.
|
|
|
|
*/
|
|
|
|
return DIFF_STATUS_MODIFIED;
|
|
|
|
}
|
|
|
|
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
static void update_callback(struct diff_queue_struct *q,
|
|
|
|
struct diff_options *opt, void *cbdata)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct update_callback_data *data = cbdata;
|
|
|
|
|
|
|
|
for (i = 0; i < q->nr; i++) {
|
|
|
|
struct diff_filepair *p = q->queue[i];
|
|
|
|
const char *path = p->one->path;
|
2011-04-21 09:11:19 +08:00
|
|
|
switch (fix_unmerged_status(p, data)) {
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
default:
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("unexpected diff status %c"), p->status);
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
case DIFF_STATUS_MODIFIED:
|
|
|
|
case DIFF_STATUS_TYPE_CHANGED:
|
2016-09-15 05:07:47 +08:00
|
|
|
if (add_file_to_index(&the_index, path, data->flags)) {
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("updating files failed"));
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
data->add_errors++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DIFF_STATUS_DELETED:
|
|
|
|
if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
|
|
|
|
break;
|
|
|
|
if (!(data->flags & ADD_CACHE_PRETEND))
|
|
|
|
remove_file_from_index(&the_index, path);
|
|
|
|
if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
|
2011-02-23 07:41:32 +08:00
|
|
|
printf(_("remove '%s'\n"), path);
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-15 05:07:47 +08:00
|
|
|
int add_files_to_cache(const char *prefix,
|
|
|
|
const struct pathspec *pathspec, int flags)
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
{
|
2014-03-08 07:14:47 +08:00
|
|
|
struct update_callback_data data;
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
struct rev_info rev;
|
2013-03-20 06:50:50 +08:00
|
|
|
|
2014-03-08 07:14:47 +08:00
|
|
|
memset(&data, 0, sizeof(data));
|
|
|
|
data.flags = flags;
|
|
|
|
|
2018-09-21 23:57:38 +08:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
setup_revisions(0, NULL, &rev, NULL);
|
2013-07-14 16:35:56 +08:00
|
|
|
if (pathspec)
|
|
|
|
copy_pathspec(&rev.prune_data, pathspec);
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
|
|
|
|
rev.diffopt.format_callback = update_callback;
|
2014-03-08 07:14:47 +08:00
|
|
|
rev.diffopt.format_callback_data = &data;
|
2017-11-01 02:19:11 +08:00
|
|
|
rev.diffopt.flags.override_submodule_config = 1;
|
2011-04-21 09:11:19 +08:00
|
|
|
rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
|
2017-09-05 21:04:10 +08:00
|
|
|
clear_pathspec(&rev.prune_data);
|
Remove diff machinery dependency from read-cache
Exal Sibeaz pointed out that some git files are way too big, and that
add_files_to_cache() brings in all the diff machinery to any git binary
that needs the basic git SHA1 object operations from read-cache.c. Which
is pretty much all of them.
It's doubly silly, since add_files_to_cache() is only used by builtin
programs (add, checkout and commit), so it's fairly easily fixed by just
moving the thing to builtin-add.c, and avoiding the dependency entirely.
I initially argued to Exal that it would probably be best to try to depend
on smart compilers and linkers, but after spending some time trying to
make -ffunction-sections work and giving up, I think Exal was right, and
the fix is to just do some trivial cleanups like this.
This trivial cleanup results in pretty stunning file size differences.
The diff machinery really is mostly used by just the builtin programs, and
you have things like these trivial before-and-after numbers:
-rwxr-xr-x 1 torvalds torvalds 1727420 2010-01-21 10:53 git-hash-object
-rwxrwxr-x 1 torvalds torvalds 940265 2010-01-21 11:16 git-hash-object
Now, I'm not saying that 940kB is good either, but that's mostly all the
debug information - you can see the real code with 'size':
text data bss dec hex filename
418675 3920 127408 550003 86473 git-hash-object (before)
230650 2288 111728 344666 5425a git-hash-object (after)
ie we have a nice 24% size reduction from this trivial cleanup.
It's not just that one file either. I get:
[torvalds@nehalem git]$ du -s /home/torvalds/libexec/git-core
45640 /home/torvalds/libexec/git-core (before)
33508 /home/torvalds/libexec/git-core (after)
so we're talking 12MB of diskspace here.
(Of course, stripping all the binaries brings the 33MB down to 9MB, so the
whole debug information thing is still the bulk of it all, but that's a
separate issue entirely)
Now, I'm sure there are other things we should do, and changing our
compiler flags from -O2 to -Os would bring the text size down by an
additional almost 20%, but this thing Exal pointed out seems to be some
good low-hanging fruit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-22 03:37:38 +08:00
|
|
|
return !!data.add_errors;
|
|
|
|
}
|
|
|
|
|
2017-11-17 00:38:28 +08:00
|
|
|
static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
|
|
|
|
{
|
|
|
|
int i, retval = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < active_nr; i++) {
|
|
|
|
struct cache_entry *ce = active_cache[i];
|
|
|
|
|
|
|
|
if (ce_stage(ce))
|
|
|
|
continue; /* do not touch unmerged paths */
|
|
|
|
if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
|
|
|
|
continue; /* do not touch non blobs */
|
2018-08-14 00:14:22 +08:00
|
|
|
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
|
2017-11-17 00:38:28 +08:00
|
|
|
continue;
|
2019-01-18 00:27:11 +08:00
|
|
|
retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE);
|
2017-11-17 00:38:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2014-03-08 07:14:01 +08:00
|
|
|
static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
|
2006-05-18 00:33:32 +08:00
|
|
|
{
|
2006-05-18 04:23:19 +08:00
|
|
|
char *seen;
|
2013-07-14 16:36:00 +08:00
|
|
|
int i;
|
2006-05-18 00:33:32 +08:00
|
|
|
struct dir_entry **src, **dst;
|
|
|
|
|
2013-07-14 16:36:00 +08:00
|
|
|
seen = xcalloc(pathspec->nr, 1);
|
2006-05-18 04:23:19 +08:00
|
|
|
|
2006-05-18 00:33:32 +08:00
|
|
|
src = dst = dir->entries;
|
|
|
|
i = dir->nr;
|
|
|
|
while (--i >= 0) {
|
|
|
|
struct dir_entry *entry = *src++;
|
2018-08-14 00:14:22 +08:00
|
|
|
if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
|
2006-12-30 03:01:31 +08:00
|
|
|
*dst++ = entry;
|
2006-05-18 00:33:32 +08:00
|
|
|
}
|
|
|
|
dir->nr = dst - dir->entries;
|
2017-05-12 06:04:27 +08:00
|
|
|
add_pathspec_matches_against_index(pathspec, &the_index, seen);
|
2010-02-10 06:30:49 +08:00
|
|
|
return seen;
|
2006-05-18 00:33:32 +08:00
|
|
|
}
|
|
|
|
|
2013-07-14 16:35:54 +08:00
|
|
|
static void refresh(int verbose, const struct pathspec *pathspec)
|
2007-08-12 05:59:01 +08:00
|
|
|
{
|
|
|
|
char *seen;
|
2013-07-14 16:35:54 +08:00
|
|
|
int i;
|
2007-08-12 05:59:01 +08:00
|
|
|
|
2013-07-14 16:35:54 +08:00
|
|
|
seen = xcalloc(pathspec->nr, 1);
|
2009-08-21 16:57:58 +08:00
|
|
|
refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
|
2011-02-23 07:41:33 +08:00
|
|
|
pathspec, seen, _("Unstaged changes after refreshing the index:"));
|
2013-07-14 16:35:54 +08:00
|
|
|
for (i = 0; i < pathspec->nr; i++) {
|
2007-08-12 05:59:01 +08:00
|
|
|
if (!seen[i])
|
2013-07-14 16:35:54 +08:00
|
|
|
die(_("pathspec '%s' did not match any files"),
|
|
|
|
pathspec->items[i].match);
|
2007-08-12 05:59:01 +08:00
|
|
|
}
|
2018-12-06 23:42:06 +08:00
|
|
|
free(seen);
|
2007-08-12 05:59:01 +08:00
|
|
|
}
|
|
|
|
|
2009-08-13 20:29:41 +08:00
|
|
|
int run_add_interactive(const char *revision, const char *patch_mode,
|
2013-07-14 16:35:50 +08:00
|
|
|
const struct pathspec *pathspec)
|
2007-09-18 08:06:44 +08:00
|
|
|
{
|
2014-03-15 19:14:40 +08:00
|
|
|
int status, i;
|
|
|
|
struct argv_array argv = ARGV_ARRAY_INIT;
|
2007-11-26 02:10:10 +08:00
|
|
|
|
2014-03-15 19:14:40 +08:00
|
|
|
argv_array_push(&argv, "add--interactive");
|
2009-08-13 20:29:41 +08:00
|
|
|
if (patch_mode)
|
2014-03-15 19:14:40 +08:00
|
|
|
argv_array_push(&argv, patch_mode);
|
2009-08-13 20:29:41 +08:00
|
|
|
if (revision)
|
2014-03-15 19:14:40 +08:00
|
|
|
argv_array_push(&argv, revision);
|
|
|
|
argv_array_push(&argv, "--");
|
2013-07-14 16:35:50 +08:00
|
|
|
for (i = 0; i < pathspec->nr; i++)
|
|
|
|
/* pass original pathspec, to be re-parsed */
|
2014-03-15 19:14:40 +08:00
|
|
|
argv_array_push(&argv, pathspec->items[i].original);
|
2007-11-22 08:02:52 +08:00
|
|
|
|
2014-03-15 19:14:40 +08:00
|
|
|
status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
|
|
|
|
argv_array_clear(&argv);
|
2007-11-22 08:02:52 +08:00
|
|
|
return status;
|
2007-09-18 08:06:44 +08:00
|
|
|
}
|
|
|
|
|
2011-05-08 01:58:07 +08:00
|
|
|
int interactive_add(int argc, const char **argv, const char *prefix, int patch)
|
2009-08-13 20:29:41 +08:00
|
|
|
{
|
2013-07-14 16:35:46 +08:00
|
|
|
struct pathspec pathspec;
|
2009-08-13 20:29:41 +08:00
|
|
|
|
2013-09-05 11:40:39 +08:00
|
|
|
parse_pathspec(&pathspec, 0,
|
2013-07-14 16:35:46 +08:00
|
|
|
PATHSPEC_PREFER_FULL |
|
2013-07-14 16:35:50 +08:00
|
|
|
PATHSPEC_SYMLINK_LEADING_PATH |
|
|
|
|
PATHSPEC_PREFIX_ORIGIN,
|
2013-07-14 16:35:46 +08:00
|
|
|
prefix, argv);
|
2009-08-13 20:29:41 +08:00
|
|
|
|
|
|
|
return run_add_interactive(NULL,
|
2011-05-08 01:58:07 +08:00
|
|
|
patch ? "--patch" : NULL,
|
2013-07-14 16:35:50 +08:00
|
|
|
&pathspec);
|
2009-08-13 20:29:41 +08:00
|
|
|
}
|
|
|
|
|
2009-06-19 01:28:43 +08:00
|
|
|
static int edit_patch(int argc, const char **argv, const char *prefix)
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
{
|
2012-09-05 01:30:21 +08:00
|
|
|
char *file = git_pathdup("ADD_EDIT.patch");
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
const char *apply_argv[] = { "apply", "--recount", "--cached",
|
2010-05-14 17:31:33 +08:00
|
|
|
NULL, NULL };
|
2014-08-20 03:09:35 +08:00
|
|
|
struct child_process child = CHILD_PROCESS_INIT;
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
struct rev_info rev;
|
|
|
|
int out;
|
|
|
|
struct stat st;
|
|
|
|
|
2010-05-14 17:31:33 +08:00
|
|
|
apply_argv[3] = file;
|
|
|
|
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
|
|
|
|
|
|
|
if (read_cache() < 0)
|
2013-08-31 05:56:49 +08:00
|
|
|
die(_("Could not read the index"));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
2018-09-21 23:57:38 +08:00
|
|
|
repo_init_revisions(the_repository, &rev, prefix);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
rev.diffopt.context = 7;
|
|
|
|
|
|
|
|
argc = setup_revisions(argc, argv, &rev, NULL);
|
|
|
|
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
|
2013-07-19 06:58:04 +08:00
|
|
|
rev.diffopt.use_color = 0;
|
2017-11-01 02:19:11 +08:00
|
|
|
rev.diffopt.flags.ignore_dirty_submodules = 1;
|
2019-01-15 23:42:52 +08:00
|
|
|
out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
if (out < 0)
|
2013-08-31 05:56:49 +08:00
|
|
|
die(_("Could not open '%s' for writing."), file);
|
2009-09-12 16:43:27 +08:00
|
|
|
rev.diffopt.file = xfdopen(out, "w");
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
rev.diffopt.close_file = 1;
|
|
|
|
if (run_diff_files(&rev, 0))
|
2013-08-31 05:56:49 +08:00
|
|
|
die(_("Could not write patch"));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
2015-05-13 09:21:58 +08:00
|
|
|
if (launch_editor(file, NULL, NULL))
|
|
|
|
die(_("editing patch failed"));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
|
|
|
if (stat(file, &st))
|
2011-02-23 07:41:29 +08:00
|
|
|
die_errno(_("Could not stat '%s'"), file);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
if (!st.st_size)
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("Empty patch. Aborted."));
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
|
|
|
child.git_cmd = 1;
|
|
|
|
child.argv = apply_argv;
|
|
|
|
if (run_command(&child))
|
2013-08-31 05:56:49 +08:00
|
|
|
die(_("Could not apply '%s'"), file);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
|
|
|
|
unlink(file);
|
2012-09-05 01:30:21 +08:00
|
|
|
free(file);
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-08-29 06:41:23 +08:00
|
|
|
static const char ignore_error[] =
|
2011-02-23 07:41:30 +08:00
|
|
|
N_("The following paths are ignored by one of your .gitignore files:\n");
|
2006-12-26 09:46:38 +08:00
|
|
|
|
2013-03-09 14:21:13 +08:00
|
|
|
static int verbose, show_only, ignored_too, refresh_only;
|
2011-04-20 03:18:20 +08:00
|
|
|
static int ignore_add_errors, intent_to_add, ignore_missing;
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
static int warn_on_embedded_repo = 1;
|
2011-04-20 03:18:20 +08:00
|
|
|
|
2013-04-23 05:30:22 +08:00
|
|
|
#define ADDREMOVE_DEFAULT 1
|
2011-04-20 03:18:20 +08:00
|
|
|
static int addremove = ADDREMOVE_DEFAULT;
|
|
|
|
static int addremove_explicit = -1; /* unspecified */
|
2007-10-04 05:45:02 +08:00
|
|
|
|
2016-06-01 06:08:18 +08:00
|
|
|
static char *chmod_arg;
|
|
|
|
|
2013-04-23 04:29:20 +08:00
|
|
|
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 */
|
|
|
|
*(int *)opt->value = !unset ? 0 : 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-10-04 05:45:02 +08:00
|
|
|
static struct option builtin_add_options[] = {
|
2012-08-20 20:31:52 +08:00
|
|
|
OPT__DRY_RUN(&show_only, N_("dry run")),
|
|
|
|
OPT__VERBOSE(&verbose, N_("be verbose")),
|
2007-10-04 05:45:02 +08:00
|
|
|
OPT_GROUP(""),
|
2013-03-09 14:21:13 +08:00
|
|
|
OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
|
|
|
|
OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
|
|
|
|
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
|
2018-02-09 19:01:42 +08:00
|
|
|
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
|
2013-03-09 14:21:13 +08:00
|
|
|
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
|
2017-11-17 00:38:28 +08:00
|
|
|
OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
|
2013-03-09 14:21:13 +08:00
|
|
|
OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
|
2011-04-20 03:18:20 +08:00
|
|
|
OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
|
2013-04-23 04:29:20 +08:00
|
|
|
{ OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
|
|
|
|
NULL /* takes no arguments */,
|
|
|
|
N_("ignore paths removed in the working tree (same as --no-all)"),
|
|
|
|
PARSE_OPT_NOARG, ignore_removal_cb },
|
2013-03-09 14:21:13 +08:00
|
|
|
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")),
|
2018-08-03 03:18:14 +08:00
|
|
|
OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
|
|
|
|
N_("override the executable bit of the listed files")),
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
|
|
|
|
N_("warn when adding an embedded repository")),
|
2007-10-04 05:45:02 +08:00
|
|
|
OPT_END(),
|
|
|
|
};
|
|
|
|
|
2008-05-26 05:25:02 +08:00
|
|
|
static int add_config(const char *var, const char *value, void *cb)
|
2008-05-13 01:59:23 +08:00
|
|
|
{
|
2011-05-15 04:19:21 +08:00
|
|
|
if (!strcmp(var, "add.ignoreerrors") ||
|
|
|
|
!strcmp(var, "add.ignore-errors")) {
|
2008-05-13 01:59:23 +08:00
|
|
|
ignore_add_errors = git_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2008-05-26 05:25:02 +08:00
|
|
|
return git_default_config(var, value, cb);
|
2008-05-13 01:59:23 +08:00
|
|
|
}
|
|
|
|
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
static const char embedded_advice[] = N_(
|
|
|
|
"You've added another git repository inside your current repository.\n"
|
|
|
|
"Clones of the outer repository will not contain the contents of\n"
|
|
|
|
"the embedded repository and will not know how to obtain it.\n"
|
|
|
|
"If you meant to add a submodule, use:\n"
|
|
|
|
"\n"
|
|
|
|
" git submodule add <url> %s\n"
|
|
|
|
"\n"
|
|
|
|
"If you added this path by mistake, you can remove it from the\n"
|
|
|
|
"index with:\n"
|
|
|
|
"\n"
|
|
|
|
" git rm --cached %s\n"
|
|
|
|
"\n"
|
|
|
|
"See \"git help submodule\" for more information."
|
|
|
|
);
|
|
|
|
|
|
|
|
static void check_embedded_repo(const char *path)
|
|
|
|
{
|
|
|
|
struct strbuf name = STRBUF_INIT;
|
|
|
|
|
|
|
|
if (!warn_on_embedded_repo)
|
|
|
|
return;
|
|
|
|
if (!ends_with(path, "/"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Drop trailing slash for aesthetics */
|
|
|
|
strbuf_addstr(&name, path);
|
|
|
|
strbuf_strip_suffix(&name, "/");
|
|
|
|
|
|
|
|
warning(_("adding embedded git repository: %s"), name.buf);
|
|
|
|
if (advice_add_embedded_repo) {
|
|
|
|
advise(embedded_advice, name.buf, name.buf);
|
|
|
|
/* there may be multiple entries; advise only once */
|
|
|
|
advice_add_embedded_repo = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
strbuf_release(&name);
|
|
|
|
}
|
|
|
|
|
2016-09-15 05:07:47 +08:00
|
|
|
static int add_files(struct dir_struct *dir, int flags)
|
2008-07-20 10:22:25 +08:00
|
|
|
{
|
|
|
|
int i, exit_status = 0;
|
|
|
|
|
|
|
|
if (dir->ignored_nr) {
|
2011-02-23 07:41:30 +08:00
|
|
|
fprintf(stderr, _(ignore_error));
|
2008-07-20 10:22:25 +08:00
|
|
|
for (i = 0; i < dir->ignored_nr; i++)
|
|
|
|
fprintf(stderr, "%s\n", dir->ignored[i]->name);
|
2011-02-23 07:41:30 +08:00
|
|
|
fprintf(stderr, _("Use -f if you really want to add them.\n"));
|
2014-11-22 00:08:19 +08:00
|
|
|
exit_status = 1;
|
2008-07-20 10:22:25 +08:00
|
|
|
}
|
|
|
|
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
for (i = 0; i < dir->nr; i++) {
|
2016-09-15 05:07:47 +08:00
|
|
|
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
|
2008-07-20 10:22:25 +08:00
|
|
|
if (!ignore_add_errors)
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("adding files failed"));
|
2008-07-20 10:22:25 +08:00
|
|
|
exit_status = 1;
|
2019-04-10 07:07:37 +08:00
|
|
|
} else {
|
|
|
|
check_embedded_repo(dir->entries[i]->name);
|
2008-07-20 10:22:25 +08:00
|
|
|
}
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 18:58:22 +08:00
|
|
|
}
|
2008-07-20 10:22:25 +08:00
|
|
|
return exit_status;
|
|
|
|
}
|
|
|
|
|
2006-07-29 13:44:25 +08:00
|
|
|
int cmd_add(int argc, const char **argv, const char *prefix)
|
2006-05-18 00:33:32 +08:00
|
|
|
{
|
2008-05-13 01:58:10 +08:00
|
|
|
int exit_status = 0;
|
2013-07-14 16:35:46 +08:00
|
|
|
struct pathspec pathspec;
|
2006-05-18 00:33:32 +08:00
|
|
|
struct dir_struct dir;
|
2016-09-15 05:07:47 +08:00
|
|
|
int flags;
|
2008-07-20 10:22:25 +08:00
|
|
|
int add_new_files;
|
|
|
|
int require_pathspec;
|
2010-02-10 06:30:49 +08:00
|
|
|
char *seen = NULL;
|
lock_file: move static locks into functions
Placing `struct lock_file`s on the stack used to be a bad idea, because
the temp- and lockfile-machinery would keep a pointer into the struct.
But after 076aa2cbd (tempfile: auto-allocate tempfiles on heap,
2017-09-05), we can safely have lockfiles on the stack. (This applies
even if a user returns early, leaving a locked lock behind.)
Each of these `struct lock_file`s is used from within a single function.
Move them into the respective functions to make the scope clearer and
drop the staticness.
For good measure, I have inspected these sites and come to believe that
they always release the lock, with the possible exception of bailing out
using `die()` or `exit()` or by returning from a `cmd_foo()`.
As pointed out by Jeff King, it would be bad if someone held on to a
`struct lock_file *` for some reason. After some grepping, I agree with
his findings: no-one appears to be doing that.
After this commit, the remaining occurrences of "static struct
lock_file" are locks that are used from within different functions. That
is, they need to remain static. (Short of more intrusive changes like
passing around pointers to non-static locks.)
Signed-off-by: Martin Ågren <martin.agren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-10 04:55:39 +08:00
|
|
|
struct lock_file lock_file = LOCK_INIT;
|
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 12:55:50 +08:00
|
|
|
|
2009-06-18 17:17:54 +08:00
|
|
|
git_config(add_config, NULL);
|
|
|
|
|
2009-05-24 02:53:12 +08:00
|
|
|
argc = parse_options(argc, argv, prefix, builtin_add_options,
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
|
2007-11-25 21:15:42 +08:00
|
|
|
if (patch_interactive)
|
|
|
|
add_interactive = 1;
|
2007-11-22 08:02:52 +08:00
|
|
|
if (add_interactive)
|
2011-05-08 01:58:07 +08:00
|
|
|
exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
|
2006-05-18 00:33:32 +08:00
|
|
|
|
git-add: introduce --edit (to edit the diff vs. the index)
With "git add -e [<files>]", Git will fire up an editor with the current
diff relative to the index (i.e. what you would get with "git diff
[<files>]").
Now you can edit the patch as much as you like, including adding/removing
lines, editing the text, whatever. Make sure, though, that the first
character of the hunk lines is still a space, a plus or a minus.
After you closed the editor, Git will adjust the line counts of the hunks
if necessary, thanks to the --recount option of apply, and commit the
patch. Except if you deleted everything, in which case nothing happens
(for obvious reasons).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-09 05:30:24 +08:00
|
|
|
if (edit_interactive)
|
|
|
|
return(edit_patch(argc, argv, prefix));
|
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
|
2011-04-20 03:18:20 +08:00
|
|
|
if (0 <= addremove_explicit)
|
|
|
|
addremove = addremove_explicit;
|
|
|
|
else if (take_worktree_changes && ADDREMOVE_DEFAULT)
|
|
|
|
addremove = 0; /* "-u" was given but not "-A" */
|
|
|
|
|
git-add --all: add all files
People sometimes find that "git add -u && git add ." are 13 keystrokes too
many. This reduces it by nine.
The support of this has been very low priority for me personally, because
I almost never do "git add ." in a directory with already tracked files,
and in a new directory, there is no point saying "git add -u".
However, for two types of people (that are very different from me), this
mode of operation may make sense and there is no reason to leave it
unsupported. That is:
(1) If you are extremely well disciplined and keep perfect .gitignore, it
always is safe to say "git add ."; or
(2) If you are extremely undisciplined and do not even know what files
you created, and you do not very much care what goes in your history,
it does not matter if "git add ." included everything.
So there it is, although I suspect I will not use it myself, ever.
It will be too much of a change that is against the expectation of the
existing users to allow "git commit -a" to include untracked files, and
it would be inconsistent if we named this new option "-a", so the short
option is "-A". We _might_ want to later add "git commit -A" but that is
a separate topic.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-20 10:51:11 +08:00
|
|
|
if (addremove && take_worktree_changes)
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("-A and -u are mutually incompatible"));
|
2011-04-20 03:18:20 +08:00
|
|
|
|
2010-07-10 06:18:38 +08:00
|
|
|
if (!show_only && ignore_missing)
|
2011-02-23 07:41:29 +08:00
|
|
|
die(_("Option --ignore-missing can only be used together with --dry-run"));
|
2013-03-20 06:53:17 +08:00
|
|
|
|
2016-09-15 05:07:47 +08:00
|
|
|
if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
|
|
|
|
chmod_arg[1] != 'x' || chmod_arg[2]))
|
2016-06-01 06:08:18 +08:00
|
|
|
die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
|
|
|
|
|
2017-11-17 00:38:28 +08:00
|
|
|
add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
|
add: simplify -u/-A without pathspec
Since Git 2.0, "add -u" and "add -A" run from a subdirectory without
any pathspec mean "everything in the working tree" (before 2.0, they
were limited to the current directory). The limiting to the current
directory was implemented by inserting "." to the command line when
the end user did not give us any pathspec. At 2.0, we updated the
code to insert ":/" (instead of '.') to consider everything from the
top-level, by using a pathspec magic "top".
The call to parse_pathspec() using the command line arguments is,
however, made with PATHSPEC_PREFER_FULL option since 5a76aff1 (add:
convert to use parse_pathspec, 2013-07-14), which predates Git 2.0.
In retrospect, there was no need to turn "adding . to limit to the
directory" into "adding :/ to unlimit to everywhere" in Git 2.0;
instead we could just have done "if there is no pathspec on the
command line, just let it be". The parse_pathspec() then would give
us a pathspec that matches everything and all is well.
Incidentally such a simplification also fixes a corner case bug that
stems from the fact that ":/" does not necessarily mean any magic.
A user would say "git --literal-pathspecs add -u :/" from the
command line when she has a directory ':' and wants to add
everything in it (and she knows that her :/ will be taken as
'everything under the sun' magic pathspec unless she disables the
magic with --literal-pathspecs). The internal use of ':/' would
behave the same way as such an explicitly given ":/" when run with
"--literal-pathspecs", and will not add everything under the sun as
the code originally intended.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-10-25 10:31:11 +08:00
|
|
|
require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
|
2008-07-20 10:22:25 +08:00
|
|
|
|
2016-12-08 02:33:54 +08:00
|
|
|
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
|
2006-05-18 00:33:32 +08:00
|
|
|
|
2013-07-14 16:35:46 +08:00
|
|
|
/*
|
|
|
|
* Check the "pathspec '%s' did not match any files" block
|
|
|
|
* below before enabling new magic.
|
|
|
|
*/
|
2018-09-19 01:31:59 +08:00
|
|
|
parse_pathspec(&pathspec, PATHSPEC_ATTR,
|
2013-07-14 16:35:46 +08:00
|
|
|
PATHSPEC_PREFER_FULL |
|
2017-05-12 06:04:24 +08:00
|
|
|
PATHSPEC_SYMLINK_LEADING_PATH,
|
2013-07-14 16:35:46 +08:00
|
|
|
prefix, argv);
|
2006-12-05 00:13:39 +08:00
|
|
|
|
2019-12-03 22:02:12 +08:00
|
|
|
if (require_pathspec && argc == 0) {
|
|
|
|
fprintf(stderr, _("Nothing specified, nothing added.\n"));
|
|
|
|
fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!take_worktree_changes && addremove_explicit < 0 && argc)
|
|
|
|
/* Turn "git add pathspec..." to "git add -A pathspec..." */
|
|
|
|
addremove = 1;
|
|
|
|
|
|
|
|
flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
|
|
|
|
(show_only ? ADD_CACHE_PRETEND : 0) |
|
|
|
|
(intent_to_add ? ADD_CACHE_INTENT : 0) |
|
|
|
|
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
|
|
|
|
(!(addremove || take_worktree_changes)
|
|
|
|
? ADD_CACHE_IGNORE_REMOVAL : 0));
|
|
|
|
|
2018-11-02 21:30:50 +08:00
|
|
|
if (read_cache_preload(&pathspec) < 0)
|
|
|
|
die(_("index file corrupt"));
|
|
|
|
|
|
|
|
die_in_unpopulated_submodule(&the_index, prefix);
|
2017-05-12 06:04:24 +08:00
|
|
|
die_path_inside_submodule(&the_index, &pathspec);
|
|
|
|
|
2009-05-15 04:22:36 +08:00
|
|
|
if (add_new_files) {
|
|
|
|
int baselen;
|
|
|
|
|
|
|
|
/* Set up the default git porcelain excludes */
|
|
|
|
memset(&dir, 0, sizeof(dir));
|
|
|
|
if (!ignored_too) {
|
|
|
|
dir.flags |= DIR_COLLECT_IGNORED;
|
|
|
|
setup_standard_excludes(&dir);
|
|
|
|
}
|
|
|
|
|
builtin-add.c: optimize -A option and "git add ."
The earlier "git add -A" change was done in a quite inefficient
way (i.e. it is as unefficient as "git add -u && git add ." modulo
one fork/exec and read/write index).
When the user asks "git add .", we do not have to examine all paths
we encounter and perform the excluded() and dir_add_name()
processing, both of which are slower code and use slower data structure
by git standards, especially when the index is already populated.
Instead, we implement "git add $pathspec..." as:
- read the index;
- read_directory() to process untracked, unignored files the current
way, that is, recursively doing readdir(), filtering them by pathspec
and excluded(), queueing them via dir_add_name() and finally do
add_files(); and
- iterate over the index, filtering them by pathspec, and update only
the modified/type changed paths but not deleted ones.
And "git add -A" becomes exactly the same as above, modulo:
- missing $pathspec means "." instead of being an error; and
- "iterate over the index" part handles deleted ones as well,
i.e. exactly what the current update_callback() in builtin-add.c does.
In either case, because fill_directory() does not use read_directory() to
read everything in, we need to add an extra logic to iterate over the
index to catch mistyped pathspec.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-23 13:30:40 +08:00
|
|
|
/* This picks up the paths that are not tracked */
|
2017-05-06 03:53:34 +08:00
|
|
|
baselen = fill_directory(&dir, &the_index, &pathspec);
|
2013-07-14 16:35:46 +08:00
|
|
|
if (pathspec.nr)
|
2014-03-08 07:14:01 +08:00
|
|
|
seen = prune_directory(&dir, &pathspec, baselen);
|
2009-05-15 04:22:36 +08:00
|
|
|
}
|
builtin-add.c: optimize -A option and "git add ."
The earlier "git add -A" change was done in a quite inefficient
way (i.e. it is as unefficient as "git add -u && git add ." modulo
one fork/exec and read/write index).
When the user asks "git add .", we do not have to examine all paths
we encounter and perform the excluded() and dir_add_name()
processing, both of which are slower code and use slower data structure
by git standards, especially when the index is already populated.
Instead, we implement "git add $pathspec..." as:
- read the index;
- read_directory() to process untracked, unignored files the current
way, that is, recursively doing readdir(), filtering them by pathspec
and excluded(), queueing them via dir_add_name() and finally do
add_files(); and
- iterate over the index, filtering them by pathspec, and update only
the modified/type changed paths but not deleted ones.
And "git add -A" becomes exactly the same as above, modulo:
- missing $pathspec means "." instead of being an error; and
- "iterate over the index" part handles deleted ones as well,
i.e. exactly what the current update_callback() in builtin-add.c does.
In either case, because fill_directory() does not use read_directory() to
read everything in, we need to add an extra logic to iterate over the
index to catch mistyped pathspec.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-23 13:30:40 +08:00
|
|
|
|
2008-07-20 10:22:25 +08:00
|
|
|
if (refresh_only) {
|
2013-07-14 16:35:54 +08:00
|
|
|
refresh(verbose, &pathspec);
|
2008-07-20 10:22:25 +08:00
|
|
|
goto finish;
|
2006-12-26 09:46:38 +08:00
|
|
|
}
|
|
|
|
|
2013-07-14 16:35:46 +08:00
|
|
|
if (pathspec.nr) {
|
2010-02-10 06:30:49 +08:00
|
|
|
int i;
|
2012-06-06 12:44:22 +08:00
|
|
|
|
2010-02-10 06:30:49 +08:00
|
|
|
if (!seen)
|
2017-05-12 06:04:27 +08:00
|
|
|
seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
|
2013-07-14 16:35:46 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* file_exists() assumes exact match
|
|
|
|
*/
|
2013-07-14 16:36:08 +08:00
|
|
|
GUARD_PATHSPEC(&pathspec,
|
|
|
|
PATHSPEC_FROMTOP |
|
|
|
|
PATHSPEC_LITERAL |
|
2013-07-14 16:36:09 +08:00
|
|
|
PATHSPEC_GLOB |
|
2013-12-06 15:30:48 +08:00
|
|
|
PATHSPEC_ICASE |
|
|
|
|
PATHSPEC_EXCLUDE);
|
2013-07-14 16:35:46 +08:00
|
|
|
|
2013-07-14 16:36:00 +08:00
|
|
|
for (i = 0; i < pathspec.nr; i++) {
|
|
|
|
const char *path = pathspec.items[i].match;
|
2013-12-06 15:30:48 +08:00
|
|
|
if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
|
|
|
|
continue;
|
2013-12-23 17:02:41 +08:00
|
|
|
if (!seen[i] && path[0] &&
|
2013-07-14 16:36:09 +08:00
|
|
|
((pathspec.items[i].magic &
|
|
|
|
(PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
|
2013-07-14 16:36:08 +08:00
|
|
|
!file_exists(path))) {
|
2010-07-10 06:18:38 +08:00
|
|
|
if (ignore_missing) {
|
2010-11-11 21:03:22 +08:00
|
|
|
int dtype = DT_UNKNOWN;
|
2017-05-06 03:53:30 +08:00
|
|
|
if (is_excluded(&dir, &the_index, path, &dtype))
|
2017-05-06 03:53:25 +08:00
|
|
|
dir_add_ignored(&dir, &the_index,
|
|
|
|
path, pathspec.items[i].len);
|
2010-07-10 06:18:38 +08:00
|
|
|
} else
|
2011-02-23 07:41:31 +08:00
|
|
|
die(_("pathspec '%s' did not match any files"),
|
2013-07-14 16:36:00 +08:00
|
|
|
pathspec.items[i].original);
|
2010-07-10 06:18:38 +08:00
|
|
|
}
|
2010-02-10 06:30:49 +08:00
|
|
|
}
|
|
|
|
free(seen);
|
|
|
|
}
|
|
|
|
|
2011-10-29 05:48:40 +08:00
|
|
|
plug_bulk_checkin();
|
|
|
|
|
2017-11-17 00:38:28 +08:00
|
|
|
if (add_renormalize)
|
|
|
|
exit_status |= renormalize_tracked_files(&pathspec, flags);
|
|
|
|
else
|
|
|
|
exit_status |= add_files_to_cache(prefix, &pathspec, flags);
|
2008-07-20 10:22:25 +08:00
|
|
|
|
|
|
|
if (add_new_files)
|
2016-09-15 05:07:47 +08:00
|
|
|
exit_status |= add_files(&dir, flags);
|
2006-05-18 00:33:32 +08:00
|
|
|
|
2016-09-15 05:07:47 +08:00
|
|
|
if (chmod_arg && pathspec.nr)
|
|
|
|
chmod_pathspec(&pathspec, chmod_arg[0]);
|
2011-10-29 05:48:40 +08:00
|
|
|
unplug_bulk_checkin();
|
|
|
|
|
2013-08-31 05:56:49 +08:00
|
|
|
finish:
|
2018-03-02 04:40:20 +08:00
|
|
|
if (write_locked_index(&the_index, &lock_file,
|
|
|
|
COMMIT_LOCK | SKIP_IF_UNCHANGED))
|
|
|
|
die(_("Unable to write new index file"));
|
2006-05-18 00:33:32 +08:00
|
|
|
|
add UNLEAK annotation for reducing leak false positives
It's a common pattern in git commands to allocate some
memory that should last for the lifetime of the program and
then not bother to free it, relying on the OS to throw it
away.
This keeps the code simple, and it's fast (we don't waste
time traversing structures or calling free at the end of the
program). But it also triggers warnings from memory-leak
checkers like valgrind or LSAN. They know that the memory
was still allocated at program exit, but they don't know
_when_ the leaked memory stopped being useful. If it was
early in the program, then it's probably a real and
important leak. But if it was used right up until program
exit, it's not an interesting leak and we'd like to suppress
it so that we can see the real leaks.
This patch introduces an UNLEAK() macro that lets us do so.
To understand its design, let's first look at some of the
alternatives.
Unfortunately the suppression systems offered by
leak-checking tools don't quite do what we want. A
leak-checker basically knows two things:
1. Which blocks were allocated via malloc, and the
callstack during the allocation.
2. Which blocks were left un-freed at the end of the
program (and which are unreachable, but more on that
later).
Their suppressions work by mentioning the function or
callstack of a particular allocation, and marking it as OK
to leak. So imagine you have code like this:
int cmd_foo(...)
{
/* this allocates some memory */
char *p = some_function();
printf("%s", p);
return 0;
}
You can say "ignore allocations from some_function(),
they're not leaks". But that's not right. That function may
be called elsewhere, too, and we would potentially want to
know about those leaks.
So you can say "ignore the callstack when main calls
some_function". That works, but your annotations are
brittle. In this case it's only two functions, but you can
imagine that the actual allocation is much deeper. If any of
the intermediate code changes, you have to update the
suppression.
What we _really_ want to say is that "the value assigned to
p at the end of the function is not a real leak". But
leak-checkers can't understand that; they don't know about
"p" in the first place.
However, we can do something a little bit tricky if we make
some assumptions about how leak-checkers work. They
generally don't just report all un-freed blocks. That would
report even globals which are still accessible when the
leak-check is run. Instead they take some set of memory
(like BSS) as a root and mark it as "reachable". Then they
scan the reachable blocks for anything that looks like a
pointer to a malloc'd block, and consider that block
reachable. And then they scan those blocks, and so on,
transitively marking anything reachable from a global as
"not leaked" (or at least leaked in a different category).
So we can mark the value of "p" as reachable by putting it
into a variable with program lifetime. One way to do that is
to just mark "p" as static. But that actually affects the
run-time behavior if the function is called twice (you
aren't likely to call main() twice, but some of our cmd_*()
functions are called from other commands).
Instead, we can trick the leak-checker by putting the value
into _any_ reachable bytes. This patch keeps a global
linked-list of bytes copied from "unleaked" variables. That
list is reachable even at program exit, which confers
recursive reachability on whatever values we unleak.
In other words, you can do:
int cmd_foo(...)
{
char *p = some_function();
printf("%s", p);
UNLEAK(p);
return 0;
}
to annotate "p" and suppress the leak report.
But wait, couldn't we just say "free(p)"? In this toy
example, yes. But UNLEAK()'s byte-copying strategy has
several advantages over actually freeing the memory:
1. It's recursive across structures. In many cases our "p"
is not just a pointer, but a complex struct whose
fields may have been allocated by a sub-function. And
in some cases (e.g., dir_struct) we don't even have a
function which knows how to free all of the struct
members.
By marking the struct itself as reachable, that confers
reachability on any pointers it contains (including those
found in embedded structs, or reachable by walking
heap blocks recursively.
2. It works on cases where we're not sure if the value is
allocated or not. For example:
char *p = argc > 1 ? argv[1] : some_function();
It's safe to use UNLEAK(p) here, because it's not
freeing any memory. In the case that we're pointing to
argv here, the reachability checker will just ignore
our bytes.
3. Likewise, it works even if the variable has _already_
been freed. We're just copying the pointer bytes. If
the block has been freed, the leak-checker will skip
over those bytes as uninteresting.
4. Because it's not actually freeing memory, you can
UNLEAK() before we are finished accessing the variable.
This is helpful in cases like this:
char *p = some_function();
return another_function(p);
Writing this with free() requires:
int ret;
char *p = some_function();
ret = another_function(p);
free(p);
return ret;
But with unleak we can just write:
char *p = some_function();
UNLEAK(p);
return another_function(p);
This patch adds the UNLEAK() macro and enables it
automatically when Git is compiled with SANITIZE=leak. In
normal builds it's a noop, so we pay no runtime cost.
It also adds some UNLEAK() annotations to show off how the
feature works. On top of other recent leak fixes, these are
enough to get t0000 and t0001 to pass when compiled with
LSAN.
Note the case in commit.c which actually converts a
strbuf_release() into an UNLEAK. This code was already
non-leaky, but the free didn't do anything useful, since
we're exiting. Converting it to an annotation means that
non-leak-checking builds pay no runtime cost. The cost is
minimal enough that it's probably not worth going on a
crusade to convert these kinds of frees to UNLEAKS. I did it
here for consistency with the "sb" leak (though it would
have been equally correct to go the other way, and turn them
both into strbuf_release() calls).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-09-08 14:38:41 +08:00
|
|
|
UNLEAK(pathspec);
|
|
|
|
UNLEAK(dir);
|
2008-05-13 01:58:10 +08:00
|
|
|
return exit_status;
|
2006-05-18 00:33:32 +08:00
|
|
|
}
|