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.
|
||||
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::
|
||||
When set to 'change', tells 'git apply' to ignore changes in
|
||||
whitespace, in the same way as the '--ignore-space-change'
|
||||
|
@ -10,7 +10,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'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]
|
||||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
||||
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
||||
@ -90,10 +90,13 @@ default. You can use `--no-utf8` to override this.
|
||||
|
||||
-3::
|
||||
--3way::
|
||||
--no-3way::
|
||||
When the patch does not apply cleanly, 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.
|
||||
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-whitespace::
|
||||
|
2
Makefile
2
Makefile
@ -467,7 +467,6 @@ TEST_PROGRAMS_NEED_X =
|
||||
# interactive shell sessions without exporting it.
|
||||
unexport CDPATH
|
||||
|
||||
SCRIPT_SH += git-am.sh
|
||||
SCRIPT_SH += git-bisect.sh
|
||||
SCRIPT_SH += git-difftool--helper.sh
|
||||
SCRIPT_SH += git-filter-branch.sh
|
||||
@ -813,6 +812,7 @@ LIB_OBJS += xdiff-interface.o
|
||||
LIB_OBJS += zlib.o
|
||||
|
||||
BUILTIN_OBJS += builtin/add.o
|
||||
BUILTIN_OBJS += builtin/am.o
|
||||
BUILTIN_OBJS += builtin/annotate.o
|
||||
BUILTIN_OBJS += builtin/apply.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 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_apply(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;
|
||||
}
|
||||
|
||||
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;
|
||||
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));
|
||||
|
||||
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)
|
||||
return WRITE_TREE_UNREADABLE_INDEX;
|
||||
if (flags & WRITE_TREE_IGNORE_CACHE_TREE)
|
||||
cache_tree_free(&(active_cache_tree));
|
||||
cache_tree_free(&index_state->cache_tree);
|
||||
|
||||
if (!active_cache_tree)
|
||||
active_cache_tree = cache_tree();
|
||||
if (!index_state->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 (cache_tree_update(&the_index, flags) < 0)
|
||||
if (cache_tree_update(index_state, flags) < 0)
|
||||
return WRITE_TREE_UNMERGED_INDEX;
|
||||
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;
|
||||
}
|
||||
/* 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) {
|
||||
struct cache_tree *subtree =
|
||||
cache_tree_find(active_cache_tree, prefix);
|
||||
struct cache_tree *subtree;
|
||||
subtree = cache_tree_find(index_state->cache_tree, prefix);
|
||||
if (!subtree)
|
||||
return WRITE_TREE_PREFIX_ERROR;
|
||||
hashcpy(sha1, subtree->sha1);
|
||||
}
|
||||
else
|
||||
hashcpy(sha1, active_cache_tree->sha1);
|
||||
hashcpy(sha1, index_state->cache_tree->sha1);
|
||||
|
||||
if (0 <= newfd)
|
||||
rollback_lock_file(lock_file);
|
||||
@ -646,6 +646,11 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
|
||||
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)
|
||||
{
|
||||
struct tree_desc desc;
|
||||
|
@ -46,6 +46,7 @@ int update_main_cache_tree(int);
|
||||
#define WRITE_TREE_UNMERGED_INDEX (-2)
|
||||
#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);
|
||||
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 *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 int xopen(const char *path, int flags, ...);
|
||||
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 xpread(int fd, void *buf, size_t len, off_t offset);
|
||||
extern int xdup(int fd);
|
||||
extern FILE *xfopen(const char *path, const char *mode);
|
||||
extern FILE *xfdopen(int fd, const char *mode);
|
||||
extern int xmkstemp(char *template);
|
||||
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[] = {
|
||||
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "am", cmd_am, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "annotate", cmd_annotate, RUN_SETUP },
|
||||
{ "apply", cmd_apply, RUN_SETUP_GENTLY },
|
||||
{ "archive", cmd_archive },
|
||||
|
@ -551,6 +551,25 @@ test_expect_success 'am -3 -p0 can read --no-prefix patch' '
|
||||
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' '
|
||||
grep "^rename from" rename.patch &&
|
||||
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
|
||||
|
||||
/**
|
||||
* 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()
|
||||
* operations with a recoverable error (EAGAIN and EINTR). xread()
|
||||
@ -311,6 +346,27 @@ int xdup(int fd)
|
||||
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 *stream = fdopen(fd, mode);
|
||||
|
Loading…
Reference in New Issue
Block a user