mirror of
https://github.com/git/git
synced 2024-09-12 21:04:12 +00:00
Merge branch 'pt/am-builtin'
Rewrite "am" in "C". * pt/am-builtin: (46 commits) git-am: add am.threeWay config variable builtin-am: remove redirection to git-am.sh builtin-am: check for valid committer ident builtin-am: implement legacy -b/--binary option builtin-am: implement -i/--interactive builtin-am: support and auto-detect mercurial patches builtin-am: support and auto-detect StGit series files builtin-am: support and auto-detect StGit patches builtin-am: rerere support builtin-am: invoke post-applypatch hook builtin-am: invoke pre-applypatch hook builtin-am: invoke applypatch-msg hook builtin-am: support automatic notes copying builtin-am: invoke post-rewrite hook builtin-am: implement -S/--gpg-sign, commit.gpgsign builtin-am: implement --committer-date-is-author-date builtin-am: implement --ignore-date builtin-am: pass git-apply's options to git-apply builtin-am: implement --[no-]scissors builtin-am: support --keep-cr, am.keepcr ...
This commit is contained in:
commit
7aa2da6162
|
@ -769,6 +769,14 @@ am.keepcr::
|
||||||
by giving '--no-keep-cr' from the command line.
|
by giving '--no-keep-cr' from the command line.
|
||||||
See linkgit:git-am[1], linkgit:git-mailsplit[1].
|
See linkgit:git-am[1], linkgit:git-mailsplit[1].
|
||||||
|
|
||||||
|
am.threeWay::
|
||||||
|
By default, `git am` will fail if the patch does not apply cleanly. When
|
||||||
|
set to true, this setting tells `git am` to fall back on 3-way merge if
|
||||||
|
the patch records the identity of blobs it is supposed to apply to and
|
||||||
|
we have those blobs available locally (equivalent to giving the `--3way`
|
||||||
|
option from the command line). Defaults to `false`.
|
||||||
|
See linkgit:git-am[1].
|
||||||
|
|
||||||
apply.ignoreWhitespace::
|
apply.ignoreWhitespace::
|
||||||
When set to 'change', tells 'git apply' to ignore changes in
|
When set to 'change', tells 'git apply' to ignore changes in
|
||||||
whitespace, in the same way as the '--ignore-space-change'
|
whitespace, in the same way as the '--ignore-space-change'
|
||||||
|
|
|
@ -10,7 +10,7 @@ SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git am' [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8]
|
'git am' [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8]
|
||||||
[--3way] [--interactive] [--committer-date-is-author-date]
|
[--[no-]3way] [--interactive] [--committer-date-is-author-date]
|
||||||
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
|
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
|
||||||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
||||||
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
||||||
|
@ -90,10 +90,13 @@ default. You can use `--no-utf8` to override this.
|
||||||
|
|
||||||
-3::
|
-3::
|
||||||
--3way::
|
--3way::
|
||||||
|
--no-3way::
|
||||||
When the patch does not apply cleanly, fall back on
|
When the patch does not apply cleanly, fall back on
|
||||||
3-way merge if the patch records the identity of blobs
|
3-way merge if the patch records the identity of blobs
|
||||||
it is supposed to apply to and we have those blobs
|
it is supposed to apply to and we have those blobs
|
||||||
available locally.
|
available locally. `--no-3way` can be used to override
|
||||||
|
am.threeWay configuration variable. For more information,
|
||||||
|
see am.threeWay in linkgit:git-config[1].
|
||||||
|
|
||||||
--ignore-space-change::
|
--ignore-space-change::
|
||||||
--ignore-whitespace::
|
--ignore-whitespace::
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -467,7 +467,6 @@ TEST_PROGRAMS_NEED_X =
|
||||||
# interactive shell sessions without exporting it.
|
# interactive shell sessions without exporting it.
|
||||||
unexport CDPATH
|
unexport CDPATH
|
||||||
|
|
||||||
SCRIPT_SH += git-am.sh
|
|
||||||
SCRIPT_SH += git-bisect.sh
|
SCRIPT_SH += git-bisect.sh
|
||||||
SCRIPT_SH += git-difftool--helper.sh
|
SCRIPT_SH += git-difftool--helper.sh
|
||||||
SCRIPT_SH += git-filter-branch.sh
|
SCRIPT_SH += git-filter-branch.sh
|
||||||
|
@ -813,6 +812,7 @@ LIB_OBJS += xdiff-interface.o
|
||||||
LIB_OBJS += zlib.o
|
LIB_OBJS += zlib.o
|
||||||
|
|
||||||
BUILTIN_OBJS += builtin/add.o
|
BUILTIN_OBJS += builtin/add.o
|
||||||
|
BUILTIN_OBJS += builtin/am.o
|
||||||
BUILTIN_OBJS += builtin/annotate.o
|
BUILTIN_OBJS += builtin/annotate.o
|
||||||
BUILTIN_OBJS += builtin/apply.o
|
BUILTIN_OBJS += builtin/apply.o
|
||||||
BUILTIN_OBJS += builtin/archive.o
|
BUILTIN_OBJS += builtin/archive.o
|
||||||
|
|
|
@ -30,6 +30,7 @@ extern int textconv_object(const char *path, unsigned mode, const unsigned char
|
||||||
extern int is_builtin(const char *s);
|
extern int is_builtin(const char *s);
|
||||||
|
|
||||||
extern int cmd_add(int argc, const char **argv, const char *prefix);
|
extern int cmd_add(int argc, const char **argv, const char *prefix);
|
||||||
|
extern int cmd_am(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_annotate(int argc, const char **argv, const char *prefix);
|
extern int cmd_annotate(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_apply(int argc, const char **argv, const char *prefix);
|
extern int cmd_apply(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_archive(int argc, const char **argv, const char *prefix);
|
extern int cmd_archive(int argc, const char **argv, const char *prefix);
|
||||||
|
|
2321
builtin/am.c
Normal file
2321
builtin/am.c
Normal file
File diff suppressed because it is too large
Load diff
29
cache-tree.c
29
cache-tree.c
|
@ -592,7 +592,7 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
|
int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
|
||||||
{
|
{
|
||||||
int entries, was_valid, newfd;
|
int entries, was_valid, newfd;
|
||||||
struct lock_file *lock_file;
|
struct lock_file *lock_file;
|
||||||
|
@ -603,23 +603,23 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
|
||||||
*/
|
*/
|
||||||
lock_file = xcalloc(1, sizeof(struct lock_file));
|
lock_file = xcalloc(1, sizeof(struct lock_file));
|
||||||
|
|
||||||
newfd = hold_locked_index(lock_file, 1);
|
newfd = hold_lock_file_for_update(lock_file, index_path, LOCK_DIE_ON_ERROR);
|
||||||
|
|
||||||
entries = read_cache();
|
entries = read_index_from(index_state, index_path);
|
||||||
if (entries < 0)
|
if (entries < 0)
|
||||||
return WRITE_TREE_UNREADABLE_INDEX;
|
return WRITE_TREE_UNREADABLE_INDEX;
|
||||||
if (flags & WRITE_TREE_IGNORE_CACHE_TREE)
|
if (flags & WRITE_TREE_IGNORE_CACHE_TREE)
|
||||||
cache_tree_free(&(active_cache_tree));
|
cache_tree_free(&index_state->cache_tree);
|
||||||
|
|
||||||
if (!active_cache_tree)
|
if (!index_state->cache_tree)
|
||||||
active_cache_tree = cache_tree();
|
index_state->cache_tree = cache_tree();
|
||||||
|
|
||||||
was_valid = cache_tree_fully_valid(active_cache_tree);
|
was_valid = cache_tree_fully_valid(index_state->cache_tree);
|
||||||
if (!was_valid) {
|
if (!was_valid) {
|
||||||
if (cache_tree_update(&the_index, flags) < 0)
|
if (cache_tree_update(index_state, flags) < 0)
|
||||||
return WRITE_TREE_UNMERGED_INDEX;
|
return WRITE_TREE_UNMERGED_INDEX;
|
||||||
if (0 <= newfd) {
|
if (0 <= newfd) {
|
||||||
if (!write_locked_index(&the_index, lock_file, COMMIT_LOCK))
|
if (!write_locked_index(index_state, lock_file, COMMIT_LOCK))
|
||||||
newfd = -1;
|
newfd = -1;
|
||||||
}
|
}
|
||||||
/* Not being able to write is fine -- we are only interested
|
/* Not being able to write is fine -- we are only interested
|
||||||
|
@ -631,14 +631,14 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
struct cache_tree *subtree =
|
struct cache_tree *subtree;
|
||||||
cache_tree_find(active_cache_tree, prefix);
|
subtree = cache_tree_find(index_state->cache_tree, prefix);
|
||||||
if (!subtree)
|
if (!subtree)
|
||||||
return WRITE_TREE_PREFIX_ERROR;
|
return WRITE_TREE_PREFIX_ERROR;
|
||||||
hashcpy(sha1, subtree->sha1);
|
hashcpy(sha1, subtree->sha1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hashcpy(sha1, active_cache_tree->sha1);
|
hashcpy(sha1, index_state->cache_tree->sha1);
|
||||||
|
|
||||||
if (0 <= newfd)
|
if (0 <= newfd)
|
||||||
rollback_lock_file(lock_file);
|
rollback_lock_file(lock_file);
|
||||||
|
@ -646,6 +646,11 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
|
||||||
|
{
|
||||||
|
return write_index_as_tree(sha1, &the_index, get_index_file(), flags, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
|
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
|
||||||
{
|
{
|
||||||
struct tree_desc desc;
|
struct tree_desc desc;
|
||||||
|
|
|
@ -46,6 +46,7 @@ int update_main_cache_tree(int);
|
||||||
#define WRITE_TREE_UNMERGED_INDEX (-2)
|
#define WRITE_TREE_UNMERGED_INDEX (-2)
|
||||||
#define WRITE_TREE_PREFIX_ERROR (-3)
|
#define WRITE_TREE_PREFIX_ERROR (-3)
|
||||||
|
|
||||||
|
int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
|
||||||
int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix);
|
int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix);
|
||||||
void prime_cache_tree(struct index_state *, struct tree *);
|
void prime_cache_tree(struct index_state *, struct tree *);
|
||||||
|
|
||||||
|
|
|
@ -717,10 +717,12 @@ extern void *xrealloc(void *ptr, size_t size);
|
||||||
extern void *xcalloc(size_t nmemb, size_t size);
|
extern void *xcalloc(size_t nmemb, size_t size);
|
||||||
extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
|
extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
|
||||||
extern void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset);
|
extern void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset);
|
||||||
|
extern int xopen(const char *path, int flags, ...);
|
||||||
extern ssize_t xread(int fd, void *buf, size_t len);
|
extern ssize_t xread(int fd, void *buf, size_t len);
|
||||||
extern ssize_t xwrite(int fd, const void *buf, size_t len);
|
extern ssize_t xwrite(int fd, const void *buf, size_t len);
|
||||||
extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
|
extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
|
||||||
extern int xdup(int fd);
|
extern int xdup(int fd);
|
||||||
|
extern FILE *xfopen(const char *path, const char *mode);
|
||||||
extern FILE *xfdopen(int fd, const char *mode);
|
extern FILE *xfdopen(int fd, const char *mode);
|
||||||
extern int xmkstemp(char *template);
|
extern int xmkstemp(char *template);
|
||||||
extern int xmkstemp_mode(char *template, int mode);
|
extern int xmkstemp_mode(char *template, int mode);
|
||||||
|
|
1
git.c
1
git.c
|
@ -370,6 +370,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
|
||||||
|
|
||||||
static struct cmd_struct commands[] = {
|
static struct cmd_struct commands[] = {
|
||||||
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
|
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
|
||||||
|
{ "am", cmd_am, RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "annotate", cmd_annotate, RUN_SETUP },
|
{ "annotate", cmd_annotate, RUN_SETUP },
|
||||||
{ "apply", cmd_apply, RUN_SETUP_GENTLY },
|
{ "apply", cmd_apply, RUN_SETUP_GENTLY },
|
||||||
{ "archive", cmd_archive },
|
{ "archive", cmd_archive },
|
||||||
|
|
|
@ -551,6 +551,25 @@ test_expect_success 'am -3 -p0 can read --no-prefix patch' '
|
||||||
git diff --exit-code lorem
|
git diff --exit-code lorem
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
|
||||||
|
rm -fr .git/rebase-apply &&
|
||||||
|
git reset --hard &&
|
||||||
|
git checkout -b lorem4 base3way &&
|
||||||
|
test_config am.threeWay 1 &&
|
||||||
|
git am lorem-move.patch &&
|
||||||
|
test_path_is_missing .git/rebase-apply &&
|
||||||
|
git diff --exit-code lorem
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'am with config am.threeWay overridden by --no-3way' '
|
||||||
|
rm -fr .git/rebase-apply &&
|
||||||
|
git reset --hard &&
|
||||||
|
git checkout -b lorem5 base3way &&
|
||||||
|
test_config am.threeWay 1 &&
|
||||||
|
test_must_fail git am --no-3way lorem-move.patch &&
|
||||||
|
test_path_is_dir .git/rebase-apply
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'am can rename a file' '
|
test_expect_success 'am can rename a file' '
|
||||||
grep "^rename from" rename.patch &&
|
grep "^rename from" rename.patch &&
|
||||||
rm -fr .git/rebase-apply &&
|
rm -fr .git/rebase-apply &&
|
||||||
|
|
56
wrapper.c
56
wrapper.c
|
@ -189,6 +189,41 @@ void *xcalloc(size_t nmemb, size_t size)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xopen() is the same as open(), but it die()s if the open() fails.
|
||||||
|
*/
|
||||||
|
int xopen(const char *path, int oflag, ...)
|
||||||
|
{
|
||||||
|
mode_t mode = 0;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* va_arg() will have undefined behavior if the specified type is not
|
||||||
|
* compatible with the argument type. Since integers are promoted to
|
||||||
|
* ints, we fetch the next argument as an int, and then cast it to a
|
||||||
|
* mode_t to avoid undefined behavior.
|
||||||
|
*/
|
||||||
|
va_start(ap, oflag);
|
||||||
|
if (oflag & O_CREAT)
|
||||||
|
mode = va_arg(ap, int);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int fd = open(path, oflag, mode);
|
||||||
|
if (fd >= 0)
|
||||||
|
return fd;
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((oflag & O_RDWR) == O_RDWR)
|
||||||
|
die_errno(_("could not open '%s' for reading and writing"), path);
|
||||||
|
else if ((oflag & O_WRONLY) == O_WRONLY)
|
||||||
|
die_errno(_("could not open '%s' for writing"), path);
|
||||||
|
else
|
||||||
|
die_errno(_("could not open '%s' for reading"), path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xread() is the same a read(), but it automatically restarts read()
|
* xread() is the same a read(), but it automatically restarts read()
|
||||||
* operations with a recoverable error (EAGAIN and EINTR). xread()
|
* operations with a recoverable error (EAGAIN and EINTR). xread()
|
||||||
|
@ -311,6 +346,27 @@ int xdup(int fd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xfopen() is the same as fopen(), but it die()s if the fopen() fails.
|
||||||
|
*/
|
||||||
|
FILE *xfopen(const char *path, const char *mode)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
FILE *fp = fopen(path, mode);
|
||||||
|
if (fp)
|
||||||
|
return fp;
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (*mode && mode[1] == '+')
|
||||||
|
die_errno(_("could not open '%s' for reading and writing"), path);
|
||||||
|
else if (*mode == 'w' || *mode == 'a')
|
||||||
|
die_errno(_("could not open '%s' for writing"), path);
|
||||||
|
else
|
||||||
|
die_errno(_("could not open '%s' for reading"), path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FILE *xfdopen(int fd, const char *mode)
|
FILE *xfdopen(int fd, const char *mode)
|
||||||
{
|
{
|
||||||
FILE *stream = fdopen(fd, mode);
|
FILE *stream = fdopen(fd, mode);
|
||||||
|
|
Loading…
Reference in a new issue