Code preparation for pluggable ref backends.
* dt/refs-backend-pre-vtable:
refs: break out ref conflict checks
files_log_ref_write: new function
initdb: make safe_create_dir public
refs: split filesystem-based refs code into a new file
refs/refs-internal.h: new header file
refname_is_safe(): improve docstring
pack_if_possible_fn(): use ref_type() instead of is_per_worktree_ref()
copy_msg(): rename to copy_reflog_msg()
verify_refname_available(): new function
verify_refname_available(): rename function
--- /dev/null
+Git v2.6.4 Release Notes
+========================
+
+Fixes since v2.6.3
+------------------
+
+ * The "configure" script did not test for -lpthread correctly, which
+ upset some linkers.
+
+ * Add support for talking http/https over socks proxy.
+
+ * Portability fix for Windows, which may rewrite $SHELL variable using
+ non-POSIX paths.
+
+ * We now consistently allow all hooks to ignore their standard input,
+ rather than having git complain of SIGPIPE.
+
+ * Fix shell quoting in contrib script.
+
+ * Test portability fix for a topic in v2.6.1.
+
+ * Allow tilde-expansion in some http config variables.
+
+ * Give a useful special case "diff/show --word-diff-regex=." as an
+ example in the documentation.
+
+ * Fix for a corner case in filter-branch.
+
+ * Make git-p4 work on a detached head.
+
+ * Documentation clarification for "check-ignore" without "--verbose".
+
+ * Just like the working tree is cleaned up when the user cancelled
+ submission in P4Submit.applyCommit(), clean up the mess if "p4
+ submit" fails.
+
+ * Having a leftover .idx file without corresponding .pack file in
+ the repository hurts performance; "git gc" learned to prune them.
+
+ * The code to prepare the working tree side of temporary directory
+ for the "dir-diff" feature forgot that symbolic links need not be
+ copied (or symlinked) to the temporary area, as the code already
+ special cases and overwrites them. Besides, it was wrong to try
+ computing the object name of the target of symbolic link, which may
+ not even exist or may be a directory.
+
+ * There was no way to defeat a configured rebase.autostash variable
+ from the command line, as "git rebase --no-autostash" was missing.
+
+ * Allow "git interpret-trailers" to run outside of a Git repository.
+
+ * Produce correct "dirty" marker for shell prompts, even when we
+ are on an orphan or an unborn branch.
+
+ * Some corner cases have been fixed in string-matching done in "git
+ status".
+
+ * Apple's common crypto implementation of SHA1_Update() does not take
+ more than 4GB at a time, and we now have a compile-time workaround
+ for it.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
a superset of "--no-progress". Extend the command to support the
usual "--[no-]progress".
+ * The semantics of tranfer.hideRefs configuration variable have been
+ extended to work better with the ref "namespace" feature that lets
+ you throw unrelated bunches of repositories in a single physical
+ repository and virtually serve them as separate ones.
+
+ * send-email config variables whose values are pathnames now go
+ through the ~username/ expansion.
+
+ * bash completion learnt to TAB-complete recipient addresses given
+ to send-email.
+
+ * The credential-cache daemon can be told to ignore SIGHUP to work
+ around issue when running Git from inside emacs.
+
Performance, Internal Implementation, Development Support etc.
* With a "debug" helper, debugging of a single "git" invocation in
our test scripts has become a lot easier.
+ * The "configure" script did not test for -lpthread correctly, which
+ upset some linkers.
+
+ * Cross completed task off of subtree project's todo list.
+
+ * Test cleanups for the subtree project.
+
+ * Clean up style in an ancient test t9300.
+
+ * Work around some test flakiness with p4d.
+
+ * Fsck did not correctly detect a NUL-truncated header in a tag.
+
+ * Use a safer behavior when we hit errors verifying remote certificates.
+
+ * Speed up filter-branch for cases where we only care about rewriting
+ commits, not tree data.
+
+ * The parse-options API has been updated to make "-h" command line
+ option work more consistently in all commands.
+
+ * "git svn rebase/mkdirs" got optimized by keeping track of empty
+ directories better.
+
Also contains various documentation updates and code clean-ups.
requested range. However, we were hand-crafting a range request
and it did not kick in.
+ * Having a leftover .idx file without corresponding .pack file in
+ the repository hurts performance; "git gc" learned to prune them.
+ (merge 478f34d dk/gc-idx-wo-pack later to maint).
+
+ * Apple's common crypto implementation of SHA1_Update() does not take
+ more than 4GB at a time, and we now have a compile-time workaround
+ for it.
+ (merge 001fd7a ad/sha1-update-chunked later to maint).
+
+ * Produce correct "dirty" marker for shell prompts, even when we
+ are on an orphan or an unborn branch.
+ (merge c26f70c sg/bash-prompt-dirty-orphan later to maint).
+
* Code clean-up, minor fixes etc.
(merge 15ed07d jc/rerere later to maint).
(merge e7a7401 pt/pull-builtin later to maint).
example.com. See linkgit:gitcredentials[7] for details on how URLs are
matched.
+credentialCache.ignoreSIGHUP::
+ Tell git-credential-cache--daemon to ignore SIGHUP, instead of quitting.
+
include::diff-config.txt[]
difftool.<tool>.path::
explicitly exposing it, even if an earlier entry marked it as hidden.
If you have multiple hideRefs values, later entries override earlier ones
(and entries in more-specific config files override less-specific ones).
++
+If a namespace is in use, the namespace prefix is stripped from each
+reference before it is matched against `transfer.hiderefs` patterns.
+For example, if `refs/heads/master` is specified in `transfer.hideRefs` and
+the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master`
+is omitted from the advertisements but `refs/heads/master` and
+`refs/namespaces/bar/refs/heads/master` are still advertised as so-called
+"have" lines. In order to match refs before stripping, add a `^` in front of
+the ref name. If you combine `!` and `^`, `!` must be specified first.
transfer.unpackLimit::
When `fetch.unpackLimit` or `receive.unpackLimit` are
A match that contains a newline is silently truncated(!) at the
newline.
+
+For example, `--word-diff-regex=.` will treat each character as a word
+and, correspondingly, show differences character by character.
++
The regex can also be set via a diff driver or configuration option, see
linkgit:gitattributes[1] or linkgit:git-config[1]. Giving it explicitly
overrides any diff driver or configuration setting. Diff drivers
-----------
For each pathname given via the command-line or from a file via
-`--stdin`, show the pattern from .gitignore (or other input files to
-the exclude mechanism) that decides if the pathname is excluded or
-included. Later patterns within a file take precedence over earlier
-ones.
+`--stdin`, check whether the file is excluded by .gitignore (or other
+input files to the exclude mechanism) and output the path if it is
+excluded.
By default, tracked files are not shown at all since they are not
subject to exclude rules; but see `--no-index'.
-v, --verbose::
Also output details about the matching pattern (if any)
- for each given pathname.
+ for each given pathname. For precedence rules within and
+ between exclude sources, see linkgit:gitignore[5].
--stdin::
Read pathnames from the standard input, one per line,
--------
[verse]
'git send-email' [options] <file|directory|rev-list options>...
+'git send-email' --dump-aliases
DESCRIPTION
Send emails even if safety checks would prevent it.
+Information
+~~~~~~~~~~~
+
+--dump-aliases::
+ Instead of the normal operation, dump the shorthand alias names from
+ the configured alias file(s), one per line in alphabetical order. Note,
+ this only includes the alias name and not its expanded email addresses.
+ See 'sendemail.aliasesfile' for more information about aliases.
+
+
CONFIGURATION
-------------
[--[no-]assume-unchanged]
[--[no-]skip-worktree]
[--ignore-submodules]
+ [--[no-|force-]untracked-cache]
[--really-refresh] [--unresolve] [--again | -g]
[--info-only] [--index-info]
[-z] [--stdin] [--index-version <n>]
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v2.6.3/git.html[documentation for release 2.6.3]
+* link:v2.6.4/git.html[documentation for release 2.6.4]
* release notes for
+ link:RelNotes/2.6.4.txt[2.6.4],
link:RelNotes/2.6.3.txt[2.6.3],
link:RelNotes/2.6.2.txt[2.6.2],
link:RelNotes/2.6.1.txt[2.6.1],
cloning of shallow repositories.
See 'GIT_TRACE' for available trace output options.
-GIT_LITERAL_PATHSPECS::
+'GIT_LITERAL_PATHSPECS'::
Setting this variable to `1` will cause Git to treat all
pathspecs literally, rather than as glob patterns. For example,
running `GIT_LITERAL_PATHSPECS=1 git log -- '*.c'` will search
literal paths to Git (e.g., paths previously given to you by
`git ls-tree`, `--raw` diff output, etc).
-GIT_GLOB_PATHSPECS::
+'GIT_GLOB_PATHSPECS'::
Setting this variable to `1` will cause Git to treat all
pathspecs as glob patterns (aka "glob" magic).
-GIT_NOGLOB_PATHSPECS::
+'GIT_NOGLOB_PATHSPECS'::
Setting this variable to `1` will cause Git to treat all
pathspecs as literal (aka "literal" magic).
-GIT_ICASE_PATHSPECS::
+'GIT_ICASE_PATHSPECS'::
Setting this variable to `1` will cause Git to treat all
pathspecs as case-insensitive.
variable when it is invoked as the top level command by the
end user, to be recorded in the body of the reflog.
-`GIT_REF_PARANOIA`::
+'GIT_REF_PARANOIA'::
If set to `1`, include broken or badly named refs when iterating
over lists of refs. In a normal, non-corrupted repository, this
does nothing. However, enabling it may help git to detect and
an operation has touched every ref (e.g., because you are
cloning a repository to make a backup).
-`GIT_ALLOW_PROTOCOL`::
+'GIT_ALLOW_PROTOCOL'::
If set, provide a colon-separated list of protocols which are
allowed to be used with fetch/push/clone. This is useful to
restrict recursive submodule initialization from an untrusted
# Define PPC_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for PowerPC.
#
+# Define SHA1_MAX_BLOCK_SIZE to limit the amount of data that will be hashed
+# in one call to the platform's SHA1_Update(). e.g. APPLE_COMMON_CRYPTO
+# wants 'SHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' defined.
+#
# Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin).
#
# Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
BASIC_CFLAGS += -DNO_POSIX_GOODIES
endif
+ifdef APPLE_COMMON_CRYPTO
+ # Apple CommonCrypto requires chunking
+ SHA1_MAX_BLOCK_SIZE = 1024L*1024L*1024L
+endif
+
ifdef BLK_SHA1
SHA1_HEADER = "block-sha1/sha1.h"
LIB_OBJS += block-sha1/sha1.o
endif
endif
+ifdef SHA1_MAX_BLOCK_SIZE
+ LIB_OBJS += compat/sha1-chunked.o
+ BASIC_CFLAGS += -DSHA1_MAX_BLOCK_SIZE="$(SHA1_MAX_BLOCK_SIZE)"
+endif
ifdef NO_PERL_MAKEMAKER
export NO_PERL_MAKEMAKER
endif
void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len);
void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
-#define git_SHA_CTX blk_SHA_CTX
-#define git_SHA1_Init blk_SHA1_Init
-#define git_SHA1_Update blk_SHA1_Update
-#define git_SHA1_Final blk_SHA1_Final
+#define platform_SHA_CTX blk_SHA_CTX
+#define platform_SHA1_Init blk_SHA1_Init
+#define platform_SHA1_Update blk_SHA1_Update
+#define platform_SHA1_Final blk_SHA1_Final
return commit;
}
-static struct object_array_entry *find_single_final(struct rev_info *revs)
+static struct commit *find_single_final(struct rev_info *revs,
+ const char **name_p)
{
int i;
- struct object_array_entry *found = NULL;
+ struct commit *found = NULL;
+ const char *name = NULL;
for (i = 0; i < revs->pending.nr; i++) {
struct object *obj = revs->pending.objects[i].item;
die("Non commit %s?", revs->pending.objects[i].name);
if (found)
die("More than one commit to dig from %s and %s?",
- revs->pending.objects[i].name,
- found->name);
- found = &(revs->pending.objects[i]);
+ revs->pending.objects[i].name, name);
+ found = (struct commit *)obj;
+ name = revs->pending.objects[i].name;
}
+ if (name_p)
+ *name_p = name;
return found;
}
static char *prepare_final(struct scoreboard *sb)
{
- struct object_array_entry *found = find_single_final(sb->revs);
- if (found) {
- sb->final = (struct commit *) found->item;
- return xstrdup(found->name);
- } else {
- return NULL;
- }
+ const char *name;
+ sb->final = find_single_final(sb->revs, &name);
+ return xstrdup_or_null(name);
}
static char *prepare_initial(struct scoreboard *sb)
die("Cannot use --contents with final commit object name");
if (reverse && revs.first_parent_only) {
- struct object_array_entry *entry = find_single_final(sb.revs);
- if (!entry)
+ final_commit = find_single_final(sb.revs, NULL);
+ if (!final_commit)
die("--reverse and --first-parent together require specified latest commit");
- else
- final_commit = (struct commit*) entry->item;
}
/*
#include "sequencer.h"
#include "notes-utils.h"
#include "mailmap.h"
+#include "sigchain.h"
static const char * const builtin_commit_usage[] = {
N_("git commit [<options>] [--] <pathspec>..."),
return code;
n = snprintf(buf, sizeof(buf), "%s %s\n",
sha1_to_hex(oldsha1), sha1_to_hex(newsha1));
+ sigchain_push(SIGPIPE, SIG_IGN);
write_in_full(proc.in, buf, n);
close(proc.in);
+ sigchain_pop(SIGPIPE);
return finish_command(&proc);
}
static unsigned long loose, packed, packed_loose;
static off_t loose_size;
-static void real_report_garbage(const char *desc, const char *path)
+static const char *bits_to_msg(unsigned seen_bits)
+{
+ switch (seen_bits) {
+ case 0:
+ return "no corresponding .idx or .pack";
+ case PACKDIR_FILE_GARBAGE:
+ return "garbage found";
+ case PACKDIR_FILE_PACK:
+ return "no corresponding .idx";
+ case PACKDIR_FILE_IDX:
+ return "no corresponding .pack";
+ case PACKDIR_FILE_PACK|PACKDIR_FILE_IDX:
+ default:
+ return NULL;
+ }
+}
+
+static void real_report_garbage(unsigned seen_bits, const char *path)
{
struct stat st;
+ const char *desc = bits_to_msg(seen_bits);
+
+ if (!desc)
+ return;
+
if (!stat(path, &st))
size_garbage += st.st_size;
warning("%s: %s", desc, path);
static void loose_garbage(const char *path)
{
if (verbose)
- report_garbage("garbage found", path);
+ report_garbage(PACKDIR_FILE_GARBAGE, path);
}
static int count_loose(const unsigned char *sha1, const char *path, void *data)
static struct tempfile pidfile;
static struct lock_file log_lock;
+static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
+
+static void clean_pack_garbage(void)
+{
+ int i;
+ for (i = 0; i < pack_garbage.nr; i++)
+ unlink_or_warn(pack_garbage.items[i].string);
+ string_list_clear(&pack_garbage, 0);
+}
+
+static void report_pack_garbage(unsigned seen_bits, const char *path)
+{
+ if (seen_bits == PACKDIR_FILE_IDX)
+ string_list_append(&pack_garbage, path);
+}
+
static void git_config_date_string(const char *key, const char **output)
{
if (git_config_get_string_const(key, output))
if (run_command_v_opt(rerere.argv, RUN_GIT_CMD))
return error(FAILED_RUN, rerere.argv[0]);
+ report_garbage = report_pack_garbage;
+ reprepare_packed_git();
+ if (pack_garbage.nr > 0)
+ clean_pack_garbage();
+
if (auto_gc && too_many_loose_objects())
warning(_("There are too many unreachable loose objects; "
"run 'git prune' to remove them."));
return 0;
}
-static int help_callback(const struct option *opt, const char *arg, int unset)
-{
- return -1;
-}
-
int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,
N_("allow calling of grep(1) (ignored by this build)")),
- { OPTION_CALLBACK, 0, "help-all", NULL, NULL, N_("show usage"),
- PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
OPT_END()
};
- /*
- * 'git grep -h', unlike 'git grep -h <pattern>', is a request
- * to show usage information and exit.
- */
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(grep_usage, options);
-
init_grep_defaults();
git_config(grep_cmd_config, NULL);
grep_init(&opt, prefix);
*/
argc = parse_options(argc, argv, prefix, options, grep_usage,
PARSE_OPT_KEEP_DASHDASH |
- PARSE_OPT_STOP_AT_NON_OPTION |
- PARSE_OPT_NO_INTERNAL_HELP);
+ PARSE_OPT_STOP_AT_NON_OPTION);
grep_commit_pattern_type(pattern_type_arg, &opt);
if (use_index && !startup_info->have_repository)
static void show_ref(const char *path, const unsigned char *sha1)
{
- if (ref_is_hidden(path))
- return;
-
if (sent_capabilities) {
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
} else {
}
}
-static int show_ref_cb(const char *path, const struct object_id *oid, int flag, void *unused)
+static int show_ref_cb(const char *path_full, const struct object_id *oid,
+ int flag, void *unused)
{
- path = strip_namespace(path);
+ const char *path = strip_namespace(path_full);
+
+ if (ref_is_hidden(path, path_full))
+ return 0;
+
/*
* Advertise refs outside our current namespace as ".have"
* refs, so that the client can use them to minimize data
static void reject_updates_to_hidden(struct command *commands)
{
+ struct strbuf refname_full = STRBUF_INIT;
+ size_t prefix_len;
struct command *cmd;
+ strbuf_addstr(&refname_full, get_git_namespace());
+ prefix_len = refname_full.len;
+
for (cmd = commands; cmd; cmd = cmd->next) {
- if (cmd->error_string || !ref_is_hidden(cmd->ref_name))
+ if (cmd->error_string)
+ continue;
+
+ strbuf_setlen(&refname_full, prefix_len);
+ strbuf_addstr(&refname_full, cmd->ref_name);
+
+ if (!ref_is_hidden(cmd->ref_name, refname_full.buf))
continue;
if (is_null_sha1(cmd->new_sha1))
cmd->error_string = "deny deleting a hidden ref";
else
cmd->error_string = "deny updating a hidden ref";
}
+
+ strbuf_release(&refname_full);
}
static int should_process_cmd(struct command *cmd)
return 0;
}
-static int help_callback(const struct option *opt, const char *arg, int unset)
-{
- return -1;
-}
-
static const struct option show_ref_options[] = {
OPT_BOOL(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")),
OPT_BOOL(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")),
{ OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg,
N_("pattern"), N_("show refs from stdin that aren't in local repository"),
PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback },
- { OPTION_CALLBACK, 0, "help-all", NULL, NULL, N_("show usage"),
- PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
OPT_END()
};
int cmd_show_ref(int argc, const char **argv, const char *prefix)
{
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(show_ref_usage, show_ref_options);
-
argc = parse_options(argc, argv, prefix, show_ref_options,
- show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP);
+ show_ref_usage, 0);
if (exclude_arg)
return exclude_existing(exclude_existing_arg);
#include "string-list.h"
#include SHA1_HEADER
-#ifndef git_SHA_CTX
-#define git_SHA_CTX SHA_CTX
-#define git_SHA1_Init SHA1_Init
-#define git_SHA1_Update SHA1_Update
-#define git_SHA1_Final SHA1_Final
+#ifndef platform_SHA_CTX
+/*
+ * platform's underlying implementation of SHA-1; could be OpenSSL,
+ * blk_SHA, Apple CommonCrypto, etc... Note that including
+ * SHA1_HEADER may have already defined platform_SHA_CTX for our
+ * own implementations like block-sha1 and ppc-sha1, so we list
+ * the default for OpenSSL compatible SHA-1 implementations here.
+ */
+#define platform_SHA_CTX SHA_CTX
+#define platform_SHA1_Init SHA1_Init
+#define platform_SHA1_Update SHA1_Update
+#define platform_SHA1_Final SHA1_Final
+#endif
+
+#define git_SHA_CTX platform_SHA_CTX
+#define git_SHA1_Init platform_SHA1_Init
+#define git_SHA1_Update platform_SHA1_Update
+#define git_SHA1_Final platform_SHA1_Final
+
+#ifdef SHA1_MAX_BLOCK_SIZE
+#include "compat/sha1-chunked.h"
+#undef git_SHA1_Update
+#define git_SHA1_Update git_SHA1_Update_Chunked
#endif
#include <zlib.h>
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
-/* A hook for count-objects to report invalid files in pack directory */
-extern void (*report_garbage)(const char *desc, const char *path);
+/* A hook to report invalid files in pack directory */
+#define PACKDIR_FILE_PACK 1
+#define PACKDIR_FILE_IDX 2
+#define PACKDIR_FILE_GARBAGE 4
+extern void (*report_garbage)(unsigned seen_bits, const char *path);
extern void prepare_packed_git(void);
extern void reprepare_packed_git(void);
#undef TYPE_BOOL
#endif
+#ifndef SHA1_MAX_BLOCK_SIZE
+#error Using Apple Common Crypto library requires setting SHA1_MAX_BLOCK_SIZE
+#endif
+
#ifdef APPLE_LION_OR_NEWER
#define git_CC_error_check(pattern, err) \
do { \
--- /dev/null
+#include "cache.h"
+
+int git_SHA1_Update_Chunked(platform_SHA_CTX *c, const void *data, size_t len)
+{
+ size_t nr;
+ size_t total = 0;
+ const char *cdata = (const char*)data;
+
+ while (len) {
+ nr = len;
+ if (nr > SHA1_MAX_BLOCK_SIZE)
+ nr = SHA1_MAX_BLOCK_SIZE;
+ platform_SHA1_Update(c, cdata, nr);
+ total += nr;
+ cdata += nr;
+ len -= nr;
+ }
+ return total;
+}
--- /dev/null
+
+int git_SHA1_Update_Chunked(platform_SHA_CTX *c, const void *data, size_t len);
# would then trigger compiler warnings on every single file we compile.
for opt in "" -mt -pthread -lpthread; do
old_CFLAGS="$CFLAGS"
- CFLAGS="$opt $CFLAGS"
+ old_LIBS="$LIBS"
+ case "$opt" in
+ -l*) LIBS="$opt $LIBS" ;;
+ *) CFLAGS="$opt $CFLAGS" ;;
+ esac
+
AC_MSG_CHECKING([for POSIX Threads with '$opt'])
AC_LINK_IFELSE([PTHREADTEST_SRC],
[AC_MSG_RESULT([yes])
],
[AC_MSG_RESULT([no])])
CFLAGS="$old_CFLAGS"
+ LIBS="$old_LIBS"
done
if test $threads_found != yes; then
AC_CHECK_LIB([pthread], [pthread_create],
# *) local and remote tag names
# *) .git/remotes file names
# *) git 'subcommands'
+# *) git email aliases for git-send-email
# *) tree paths within 'ref:path/to/file' expressions
# *) file paths within current working directory and index
# *) common --long-options
_git_send_email ()
{
+ case "$prev" in
+ --to|--cc|--bcc|--from)
+ __gitcomp "
+ $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null)
+ " "" ""
+ return
+ ;;
+ esac
+
case "$cur" in
--confirm=*)
__gitcomp "
" "" "${cur##--thread=}"
return
;;
+ --to=*|--cc=*|--bcc=*|--from=*)
+ __gitcomp "
+ $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null)
+ " "" "${cur#--*=}"
+ return
+ ;;
--*)
__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
--compose --confirm= --dry-run --envelope-sender
if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
[ "$(git config --bool bash.showDirtyState)" != "false" ]
then
- git diff --no-ext-diff --quiet --exit-code || w="*"
- if [ -n "$short_sha" ]; then
- git diff-index --cached --quiet HEAD -- || i="+"
- else
+ git diff --no-ext-diff --quiet || w="*"
+ git diff --no-ext-diff --cached --quiet || i="+"
+ if [ -z "$short_sha" ] && [ -z "$i" ]; then
i="#"
fi
fi
SUBDIRECTORY_OK=Yes
OPTIONS_SPEC=
-. $(git --exec-path)/git-sh-setup
+. "$(git --exec-path)/git-sh-setup"
require_work_tree
cd_to_toplevel
--annotate) annotate="$1"; shift ;;
--no-annotate) annotate= ;;
-b) branch="$1"; shift ;;
- -P) prefix="$1"; shift ;;
+ -P) prefix="${1%/}"; shift ;;
-m) message="$1"; shift ;;
--no-prefix) prefix= ;;
--onto) onto="$1"; shift ;;
RM ?= rm -f
PROVE ?= prove
DEFAULT_TEST_TARGET ?= test
+TEST_LINT ?= test-lint
+
+ifdef TEST_OUTPUT_DIRECTORY
+TEST_RESULTS_DIRECTORY = $(TEST_OUTPUT_DIRECTORY)/test-results
+else
+TEST_RESULTS_DIRECTORY = ../../../t/test-results
+endif
# Shell quote;
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
+PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
+TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY))
-T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
+T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
+TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
+TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
+THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
all: $(DEFAULT_TEST_TARGET)
prove: pre-clean $(TEST_LINT)
@echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
- $(MAKE) clean
+ $(MAKE) clean-except-prove-cache
$(T):
@echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
pre-clean:
- $(RM) -r test-results
+ $(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
-clean:
- $(RM) -r 'trash directory'.* test-results
+clean-except-prove-cache:
+ $(RM) -r 'trash directory'.* '$(TEST_RESULTS_DIRECTORY_SQ)'
$(RM) -r valgrind/bin
+
+clean: clean-except-prove-cache
$(RM) .prove
-test-lint: test-lint-duplicates test-lint-executable
+test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
test-lint-duplicates:
@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
test -z "$$bad" || { \
echo >&2 "non-executable tests:" $$bad; exit 1; }
+test-lint-shell-syntax:
+ @'$(PERL_PATH_SQ)' ../../../t/check-non-portable-shell.pl $(T) $(THELPERS)
+
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
$(MAKE) clean
aggregate-results:
- for f in ../../../t/test-results/t*-*.counts; do \
+ for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \
echo "$$f"; \
done | '$(SHELL_PATH_SQ)' ../../../t/aggregate-results.sh
#
test_description='Basic porcelain support for subtrees
-This test verifies the basic operation of the merge, pull, add
+This test verifies the basic operation of the add, pull, merge
and split subcommands of git subtree.
'
. ../../../t/test-lib.sh
+subtree_test_create_repo()
+{
+ test_create_repo "$1"
+ (
+ cd $1
+ git config log.date relative
+ )
+}
+
create()
{
echo "$1" >"$1"
git add "$1"
}
-
check_equal()
{
test_debug 'echo'
git reset --hard HEAD~
}
-last_commit_message()
+# Make sure no patch changes more than one file.
+# The original set of commits changed only one file each.
+# A multi-file change would imply that we pruned commits
+# too aggressively.
+join_commits()
{
- git log --pretty=format:%s -1
+ commit=
+ all=
+ while read x y; do
+ if [ -z "$x" ]; then
+ continue
+ elif [ "$x" = "commit:" ]; then
+ if [ -n "$commit" ]; then
+ echo "$commit $all"
+ all=
+ fi
+ commit="$y"
+ else
+ all="$all $y"
+ fi
+ done
+ echo "$commit $all"
}
-test_expect_success 'init subproj' '
- test_create_repo "sub proj"
-'
-
-# To the subproject!
-cd ./"sub proj"
-
-test_expect_success 'add sub1' '
- create sub1 &&
- git commit -m "sub1" &&
- git branch sub1 &&
- git branch -m master subproj
-'
-
-# Save this hash for testing later.
-
-subdir_hash=$(git rev-parse HEAD)
-
-test_expect_success 'add sub2' '
- create sub2 &&
- git commit -m "sub2" &&
- git branch sub2
-'
-
-test_expect_success 'add sub3' '
- create sub3 &&
- git commit -m "sub3" &&
- git branch sub3
-'
-
-# Back to mainline
-cd ..
-
-test_expect_success 'enable log.date=relative to catch errors' '
- git config log.date relative
-'
-
-test_expect_success 'add main4' '
- create main4 &&
- git commit -m "main4" &&
- git branch -m master mainline &&
- git branch subdir
-'
-
-test_expect_success 'fetch subproj history' '
- git fetch ./"sub proj" sub1 &&
- git branch sub1 FETCH_HEAD
-'
-
-test_expect_success 'no subtree exists in main tree' '
- test_must_fail git subtree merge --prefix="sub dir" sub1
-'
-
-test_expect_success 'no pull from non-existant subtree' '
- test_must_fail git subtree pull --prefix="sub dir" ./"sub proj" sub1
-'
-
-test_expect_success 'check if --message works for add' '
- git subtree add --prefix="sub dir" --message="Added subproject" sub1 &&
- check_equal ''"$(last_commit_message)"'' "Added subproject" &&
- undo
-'
-
-test_expect_success 'check if --message works as -m and --prefix as -P' '
- git subtree add -P "sub dir" -m "Added subproject using git subtree" sub1 &&
- check_equal ''"$(last_commit_message)"'' "Added subproject using git subtree" &&
- undo
-'
-
-test_expect_success 'check if --message works with squash too' '
- git subtree add -P "sub dir" -m "Added subproject with squash" --squash sub1 &&
- check_equal ''"$(last_commit_message)"'' "Added subproject with squash" &&
- undo
-'
-
-test_expect_success 'add subproj to mainline' '
- git subtree add --prefix="sub dir"/ FETCH_HEAD &&
- check_equal ''"$(last_commit_message)"'' "Add '"'sub dir/'"' from commit '"'"'''"$(git rev-parse sub1)"'''"'"'"
-'
-
-# this shouldn't actually do anything, since FETCH_HEAD is already a parent
-test_expect_success 'merge fetched subproj' '
- git merge -m "merge -s -ours" -s ours FETCH_HEAD
-'
-
-test_expect_success 'add main-sub5' '
- create "sub dir/main-sub5" &&
- git commit -m "main-sub5"
-'
-
-test_expect_success 'add main6' '
- create main6 &&
- git commit -m "main6 boring"
-'
-
-test_expect_success 'add main-sub7' '
- create "sub dir/main-sub7" &&
- git commit -m "main-sub7"
-'
-
-test_expect_success 'fetch new subproj history' '
- git fetch ./"sub proj" sub2 &&
- git branch sub2 FETCH_HEAD
-'
+test_create_commit() (
+ repo=$1
+ commit=$2
+ cd "$repo"
+ mkdir -p $(dirname "$commit") \
+ || error "Could not create directory for commit"
+ echo "$commit" >"$commit"
+ git add "$commit" || error "Could not add commit"
+ git commit -m "$commit" || error "Could not commit"
+)
-test_expect_success 'check if --message works for merge' '
- git subtree merge --prefix="sub dir" -m "Merged changes from subproject" sub2 &&
- check_equal ''"$(last_commit_message)"'' "Merged changes from subproject" &&
- undo
-'
+last_commit_message()
+{
+ git log --pretty=format:%s -1
+}
-test_expect_success 'check if --message for merge works with squash too' '
- git subtree merge --prefix "sub dir" -m "Merged changes from subproject using squash" --squash sub2 &&
- check_equal ''"$(last_commit_message)"'' "Merged changes from subproject using squash" &&
- undo
-'
+subtree_test_count=0
+next_test() {
+ subtree_test_count=$(($subtree_test_count+1))
+}
-test_expect_success 'merge new subproj history into subdir' '
- git subtree merge --prefix="sub dir" FETCH_HEAD &&
- git branch pre-split &&
- check_equal ''"$(last_commit_message)"'' "Merge commit '"'"'"$(git rev-parse sub2)"'"'"' into mainline" &&
- undo
-'
+#
+# Tests for 'git subtree add'
+#
-test_expect_success 'Check that prefix argument is required for split' '
- echo "You must provide the --prefix option." > expected &&
- test_must_fail git subtree split > actual 2>&1 &&
- test_debug "printf '"'"'expected: '"'"'" &&
- test_debug "cat expected" &&
- test_debug "printf '"'"'actual: '"'"'" &&
- test_debug "cat actual" &&
- test_cmp expected actual &&
- rm -f expected actual
+next_test
+test_expect_success 'no merge from non-existent subtree' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ test_must_fail git subtree merge --prefix="sub dir" FETCH_HEAD
+ )
+'
+
+next_test
+test_expect_success 'no pull from non-existent subtree' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ test_must_fail git subtree pull --prefix="sub dir" ./"sub proj" master
+ )'
+
+next_test
+test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''"
+ )
+'
+
+next_test
+test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --message' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" --message="Added subproject" FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Added subproject"
+ )
+'
+
+next_test
+test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P and --message as -m' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add -P "sub dir" -m "Added subproject" FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Added subproject"
+ )
+'
+
+next_test
+test_expect_success 'add subproj as subtree into sub dir/ with --squash and --prefix and --message' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" --message="Added subproject with squash" --squash FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Added subproject with squash"
+ )
'
-test_expect_success 'Check that the <prefix> exists for a split' '
- echo "'"'"'non-existent-directory'"'"'" does not exist\; use "'"'"'git subtree add'"'"'" > expected &&
- test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&
- test_debug "printf '"'"'expected: '"'"'" &&
- test_debug "cat expected" &&
- test_debug "printf '"'"'actual: '"'"'" &&
- test_debug "cat actual" &&
- test_cmp expected actual
-# rm -f expected actual
-'
+#
+# Tests for 'git subtree merge'
+#
-test_expect_success 'check if --message works for split+rejoin' '
- spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
- git branch spl1 "$spl1" &&
- check_equal ''"$(last_commit_message)"'' "Split & rejoin" &&
- undo
+next_test
+test_expect_success 'merge new subproj history into sub dir/ with --prefix' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+ )
+'
+
+next_test
+test_expect_success 'merge new subproj history into sub dir/ with --prefix and --message' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" --message="Merged changes from subproject" FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Merged changes from subproject"
+ )
+'
+
+next_test
+test_expect_success 'merge new subproj history into sub dir/ with --squash and --prefix and --message' '
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ subtree_test_create_repo "$subtree_test_count" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" --message="Merged changes from subproject using squash" --squash FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Merged changes from subproject using squash"
+ )
+'
+
+next_test
+test_expect_success 'merge the added subproj again, should do nothing' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD &&
+ # this shouldn not actually do anything, since FETCH_HEAD
+ # is already a parent
+ result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) &&
+ check_equal "${result}" "Already up-to-date."
+ )
+'
+
+next_test
+test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '
+ test_create_repo "$test_count" &&
+ test_create_repo "$test_count/subproj" &&
+ test_create_commit "$test_count" main1 &&
+ test_create_commit "$test_count/subproj" sub1 &&
+ (
+ cd "$test_count" &&
+ git fetch ./subproj master &&
+ git subtree add --prefix=subdir/ FETCH_HEAD
+ ) &&
+ test_create_commit "$test_count/subproj" sub2 &&
+ (
+ cd "$test_count" &&
+ git fetch ./subproj master &&
+ git subtree merge --prefix=subdir/ FETCH_HEAD &&
+ check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+ )
'
-test_expect_success 'check split with --branch' '
- spl1=$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin) &&
- undo &&
- git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --branch splitbr1 &&
- check_equal ''"$(git rev-parse splitbr1)"'' "$spl1"
-'
+#
+# Tests for 'git subtree split'
+#
+next_test
+test_expect_success 'split requires option --prefix' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD &&
+ echo "You must provide the --prefix option." > expected &&
+ test_must_fail git subtree split > actual 2>&1 &&
+ test_debug "printf '"expected: "'" &&
+ test_debug "cat expected" &&
+ test_debug "printf '"actual: "'" &&
+ test_debug "cat actual" &&
+ test_cmp expected actual
+ )
+'
+
+next_test
+test_expect_success 'split requires path given by option --prefix must exist' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD &&
+ echo "'\''non-existent-directory'\'' does not exist; use '\''git subtree add'\''" > expected &&
+ test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&
+ test_debug "printf '"expected: "'" &&
+ test_debug "cat expected" &&
+ test_debug "printf '"actual: "'" &&
+ test_debug "cat actual" &&
+ test_cmp expected actual
+ )
+'
+
+next_test
+test_expect_success 'split sub dir/ with --rejoin' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
+ git subtree split --prefix="sub dir" --annotate="*" --rejoin &&
+ check_equal "$(last_commit_message)" "Split '\''sub dir/'\'' into commit '\''$split_hash'\''"
+ )
+ '
+
+next_test
+test_expect_success 'split sub dir/ with --rejoin and --message' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ git subtree split --prefix="sub dir" --message="Split & rejoin" --annotate="*" --rejoin &&
+ check_equal "$(last_commit_message)" "Split & rejoin"
+ )
+'
+
+next_test
+test_expect_success 'split "sub dir"/ with --branch' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br &&
+ check_equal "$(git rev-parse subproj-br)" "$split_hash"
+ )
+'
+
+next_test
test_expect_success 'check hash of split' '
- spl1=$(git subtree split --prefix "sub dir") &&
- git subtree split --prefix "sub dir" --branch splitbr1test &&
- check_equal ''"$(git rev-parse splitbr1test)"'' "$spl1" &&
- new_hash=$(git rev-parse splitbr1test~2) &&
- check_equal ''"$new_hash"'' "$subdir_hash"
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br &&
+ check_equal "$(git rev-parse subproj-br)" "$split_hash" &&
+ # Check hash of split
+ new_hash=$(git rev-parse subproj-br^2) &&
+ (
+ cd ./"sub proj" &&
+ subdir_hash=$(git rev-parse HEAD) &&
+ check_equal ''"$new_hash"'' "$subdir_hash"
+ )
+ )
+'
+
+next_test
+test_expect_success 'split "sub dir"/ with --branch for an existing branch' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git branch subproj-br FETCH_HEAD &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br &&
+ check_equal "$(git rev-parse subproj-br)" "$split_hash"
+ )
+'
+
+next_test
+test_expect_success 'split "sub dir"/ with --branch for an incompatible branch' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git branch init HEAD &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ test_must_fail git subtree split --prefix="sub dir" --branch init
+ )
'
-test_expect_success 'check split with --branch for an existing branch' '
- spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
- undo &&
- git branch splitbr2 sub1 &&
- git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --branch splitbr2 &&
- check_equal ''"$(git rev-parse splitbr2)"'' "$spl1"
-'
-
-test_expect_success 'check split with --branch for an incompatible branch' '
- test_must_fail git subtree split --prefix "sub dir" --onto FETCH_HEAD --branch subdir
-'
-
-test_expect_success 'check split+rejoin' '
- spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
- undo &&
- git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --rejoin &&
- check_equal ''"$(last_commit_message)"'' "Split '"'"'sub dir/'"'"' into commit '"'"'"$spl1"'"'"'"
-'
-
-test_expect_success 'add main-sub8' '
- create "sub dir/main-sub8" &&
- git commit -m "main-sub8"
-'
-
-# To the subproject!
-cd ./"sub proj"
-
-test_expect_success 'merge split into subproj' '
- git fetch .. spl1 &&
- git branch spl1 FETCH_HEAD &&
- git merge FETCH_HEAD
-'
-
-test_expect_success 'add sub9' '
- create sub9 &&
- git commit -m "sub9"
-'
-
-# Back to mainline
-cd ..
-
-test_expect_success 'split for sub8' '
- split2=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir/" --rejoin)"'' &&
- git branch split2 "$split2"
-'
-
-test_expect_success 'add main-sub10' '
- create "sub dir/main-sub10" &&
- git commit -m "main-sub10"
-'
-
-test_expect_success 'split for sub10' '
- spl3=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --rejoin)"'' &&
- git branch spl3 "$spl3"
-'
-
-# To the subproject!
-cd ./"sub proj"
-
-test_expect_success 'merge split into subproj' '
- git fetch .. spl3 &&
- git branch spl3 FETCH_HEAD &&
- git merge FETCH_HEAD &&
- git branch subproj-merge-spl3
-'
+#
+# Validity checking
+#
-chkm="main4
-main6"
-chkms="main-sub10
-main-sub5
-main-sub7
-main-sub8"
-chkms_sub=$(cat <<TXT | sed 's,^,sub dir/,'
-$chkms
-TXT
-)
-chks="sub1
+next_test
+test_expect_success 'make sure exactly the right set of files ends up in the subproj' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub3 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub3 &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD &&
+
+ chks="sub1
sub2
sub3
-sub9"
-chks_sub=$(cat <<TXT | sed 's,^,sub dir/,'
+sub4" &&
+ chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
$chks
TXT
-)
+) &&
+ chkms="main-sub1
+main-sub2
+main-sub3
+main-sub4" &&
+ chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
+$chkms
+TXT
+) &&
-test_expect_success 'make sure exactly the right set of files ends up in the subproj' '
- subfiles="$(git ls-files)" &&
- check_equal "$subfiles" "$chkms
+ subfiles=$(git ls-files) &&
+ check_equal "$subfiles" "$chkms
$chks"
-'
-test_expect_success 'make sure the subproj history *only* contains commits that affect the subdir' '
- allchanges=''"$(git log --name-only --pretty=format:'"''"' | sort | sed "/^$/d")"'' &&
- check_equal "$allchanges" "$chkms
+ )
+'
+
+next_test
+test_expect_success 'make sure the subproj *only* contains commits that affect the "sub dir"' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub3 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub3 &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD &&
+
+ chks="sub1
+sub2
+sub3
+sub4" &&
+ chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
+$chks
+TXT
+) &&
+ chkms="main-sub1
+main-sub2
+main-sub3
+main-sub4" &&
+ chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
+$chkms
+TXT
+) &&
+ allchanges=$(git log --name-only --pretty=format:"" | sort | sed "/^$/d") &&
+ check_equal "$allchanges" "$chkms
$chks"
+ )
'
-# Back to mainline
-cd ..
-
-test_expect_success 'pull from subproj' '
- git fetch ./"sub proj" subproj-merge-spl3 &&
- git branch subproj-merge-spl3 FETCH_HEAD &&
- git subtree pull --prefix="sub dir" ./"sub proj" subproj-merge-spl3
-'
-
+next_test
test_expect_success 'make sure exactly the right set of files ends up in the mainline' '
- mainfiles=$(git ls-files) &&
- check_equal "$mainfiles" "$chkm
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub3 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub3 &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree pull --prefix="sub dir" ./"sub proj" master &&
+
+ chkm="main1
+main2" &&
+ chks="sub1
+sub2
+sub3
+sub4" &&
+ chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
+$chks
+TXT
+) &&
+ chkms="main-sub1
+main-sub2
+main-sub3
+main-sub4" &&
+ chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
+$chkms
+TXT
+) &&
+ mainfiles=$(git ls-files) &&
+ check_equal "$mainfiles" "$chkm
$chkms_sub
$chks_sub"
+)
'
+next_test
test_expect_success 'make sure each filename changed exactly once in the entire history' '
- # main-sub?? and /subdir/main-sub?? both change, because those are the
- # changes that were split into their own history. And subdir/sub?? never
- # change, since they were *only* changed in the subtree branch.
- allchanges=''"$(git log --name-only --pretty=format:'"''"' | sort | sed "/^$/d")"'' &&
- check_equal "$allchanges" ''"$(cat <<TXT | sort
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git config log.date relative
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub3 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub3 &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree pull --prefix="sub dir" ./"sub proj" master &&
+
+ chkm="main1
+main2" &&
+ chks="sub1
+sub2
+sub3
+sub4" &&
+ chks_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
+$chks
+TXT
+) &&
+ chkms="main-sub1
+main-sub2
+main-sub3
+main-sub4" &&
+ chkms_sub=$(cat <<TXT | sed '\''s,^,sub dir/,'\''
+$chkms
+TXT
+) &&
+
+ # main-sub?? and /"sub dir"/main-sub?? both change, because those are the
+ # changes that were split into their own history. And "sub dir"/sub?? never
+ # change, since they were *only* changed in the subtree branch.
+ allchanges=$(git log --name-only --pretty=format:"" | sort | sed "/^$/d") &&
+ expected=''"$(cat <<TXT | sort
$chkms
$chkm
$chks
$chkms_sub
TXT
-)"''
+)"'' &&
+ check_equal "$allchanges" "$expected"
+ )
'
+next_test
test_expect_success 'make sure the --rejoin commits never make it into subproj' '
- check_equal ''"$(git log --pretty=format:'"'%s'"' HEAD^2 | grep -i split)"'' ""
-'
-
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub3 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub3 &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree pull --prefix="sub dir" ./"sub proj" master &&
+ check_equal "$(git log --pretty=format:"%s" HEAD^2 | grep -i split)" ""
+ )
+'
+
+next_test
test_expect_success 'make sure no "git subtree" tagged commits make it into subproj' '
- # They are meaningless to subproj since one side of the merge refers to the mainline
- check_equal ''"$(git log --pretty=format:'"'%s%n%b'"' HEAD^2 | grep "git-subtree.*:")"'' ""
-'
-
-# prepare second pair of repositories
-mkdir test2
-cd test2
-
-test_expect_success 'init main' '
- test_create_repo main
-'
-
-cd main
-
-test_expect_success 'add main1' '
- create main1 &&
- git commit -m "main1"
-'
-
-cd ..
-
-test_expect_success 'init sub' '
- test_create_repo sub
-'
-
-cd sub
-
-test_expect_success 'add sub2' '
- create sub2 &&
- git commit -m "sub2"
-'
-
-cd ../main
-
-# check if split can find proper base without --onto
-
-test_expect_success 'add sub as subdir in main' '
- git fetch ../sub master &&
- git branch sub2 FETCH_HEAD &&
- git subtree add --prefix "sub dir" sub2
-'
-
-cd ../sub
-
-test_expect_success 'add sub3' '
- create sub3 &&
- git commit -m "sub3"
-'
-
-cd ../main
-
-test_expect_success 'merge from sub' '
- git fetch ../sub master &&
- git branch sub3 FETCH_HEAD &&
- git subtree merge --prefix "sub dir" sub3
-'
-
-test_expect_success 'add main-sub4' '
- create "sub dir/main-sub4" &&
- git commit -m "main-sub4"
-'
-
-test_expect_success 'split for main-sub4 without --onto' '
- git subtree split --prefix "sub dir" --branch mainsub4
-'
-
-# at this point, the new commit parent should be sub3 if it is not,
-# something went wrong (the "newparent" of "master~" commit should
-# have been sub3, but it was not, because its cache was not set to
-# itself)
-
-test_expect_success 'check that the commit parent is sub3' '
- check_equal ''"$(git log --pretty=format:%P -1 mainsub4)"'' ''"$(git rev-parse sub3)"''
-'
-
-test_expect_success 'add main-sub5' '
- mkdir subdir2 &&
- create subdir2/main-sub5 &&
- git commit -m "main-sub5"
-'
-
-test_expect_success 'split for main-sub5 without --onto' '
- # also test that we still can split out an entirely new subtree
- # if the parent of the first commit in the tree is not empty,
- # then the new subtree has accidentally been attached to something
- git subtree split --prefix subdir2 --branch mainsub5 &&
- check_equal ''"$(git log --pretty=format:%P -1 mainsub5)"'' ""
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub3 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub3 &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub4 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin
+ ) &&
+ (
+ cd "$subtree_test_count/sub proj" &&
+ git fetch .. subproj-br &&
+ git merge FETCH_HEAD
+ ) &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree pull --prefix="sub dir" ./"sub proj" master &&
+
+ # They are meaningless to subproj since one side of the merge refers to the mainline
+ check_equal "$(git log --pretty=format:"%s%n%b" HEAD^2 | grep "git-subtree.*:")" ""
+ )
'
-# make sure no patch changes more than one file. The original set of commits
-# changed only one file each. A multi-file change would imply that we pruned
-# commits too aggressively.
-joincommits()
-{
- commit=
- all=
- while read x y; do
- #echo "{$x}" >&2
- if [ -z "$x" ]; then
- continue
- elif [ "$x" = "commit:" ]; then
- if [ -n "$commit" ]; then
- echo "$commit $all"
- all=
- fi
- commit="$y"
- else
- all="$all $y"
- fi
- done
- echo "$commit $all"
-}
+#
+# A new set of tests
+#
+next_test
+test_expect_success 'make sure "git subtree split" find the correct parent' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git branch subproj-ref FETCH_HEAD &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --branch subproj-br &&
+
+ # at this point, the new commit parent should be subproj-ref, if it is
+ # not, something went wrong (the "newparent" of "master~" commit should
+ # have been sub2, but it was not, because its cache was not set to
+ # itself)
+ check_equal "$(git log --pretty=format:%P -1 subproj-br)" "$(git rev-parse subproj-ref)"
+ )
+'
+
+next_test
+test_expect_success 'split a new subtree without --onto option' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --branch subproj-br
+ ) &&
+ mkdir "$subtree_test_count"/"sub dir2" &&
+ test_create_commit "$subtree_test_count" "sub dir2"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+
+ # also test that we still can split out an entirely new subtree
+ # if the parent of the first commit in the tree is not empty,
+ # then the new subtree has accidently been attached to something
+ git subtree split --prefix="sub dir2" --branch subproj2-br &&
+ check_equal "$(git log --pretty=format:%P -1 subproj2-br)" ""
+ )
+'
+
+next_test
test_expect_success 'verify one file change per commit' '
- x= &&
- list=''"$(git log --pretty=format:'"'commit: %H'"' | joincommits)"'' &&
-# test_debug "echo HERE" &&
-# test_debug "echo ''"$list"''" &&
- (git log --pretty=format:'"'commit: %H'"' | joincommits |
- ( while read commit a b; do
- test_debug "echo Verifying commit "''"$commit"''
- test_debug "echo a: "''"$a"''
- test_debug "echo b: "''"$b"''
- check_equal "$b" ""
- x=1
- done
- check_equal "$x" 1
- ))
-'
-
-# test push
-
-cd ../..
-
-mkdir test-push
-
-cd test-push
-
-test_expect_success 'init main' '
- test_create_repo main
-'
-
-test_expect_success 'init sub' '
- test_create_repo "sub project"
-'
-
-cd ./"sub project"
-
-test_expect_success 'add subproject' '
- create "sub project" &&
- git commit -m "Sub project: 1" &&
- git branch sub-branch-1
-'
-
-cd ../main
-
-test_expect_success 'make first commit and add subproject' '
- create "main-1" &&
- git commit -m "main: 1" &&
- git subtree add "../sub project" --prefix "sub dir" --message "Added subproject" sub-branch-1 &&
- check_equal "$(last_commit_message)" "Added subproject"
-'
-
-test_expect_success 'make second commit to a subproject file and push it into a sub project' '
- create "sub dir/sub1" &&
- git commit -m "Sub project: 2" &&
- git subtree push "../sub project" --prefix "sub dir" sub-branch-1
-'
-
-cd ../"sub project"
-
-test_expect_success 'Test second commit is pushed' '
- git checkout sub-branch-1 &&
- check_equal "$(last_commit_message)" "Sub project: 2"
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git branch sub1 FETCH_HEAD &&
+ git subtree add --prefix="sub dir" sub1
+ ) &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir" --branch subproj-br
+ ) &&
+ mkdir "$subtree_test_count"/"sub dir2" &&
+ test_create_commit "$subtree_test_count" "sub dir2"/main-sub2 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree split --prefix="sub dir2" --branch subproj2-br &&
+
+ x= &&
+ git log --pretty=format:"commit: %H" | join_commits |
+ (
+ while read commit a b; do
+ test_debug "echo Verifying commit $commit"
+ test_debug "echo a: $a"
+ test_debug "echo b: $b"
+ check_equal "$b" ""
+ x=1
+ done
+ check_equal "$x" 1
+ )
+ )
+'
+
+next_test
+test_expect_success 'push split to subproj' '
+ subtree_test_create_repo "$subtree_test_count" &&
+ subtree_test_create_repo "$subtree_test_count/sub proj" &&
+ test_create_commit "$subtree_test_count" main1 &&
+ test_create_commit "$subtree_test_count/sub proj" sub1 &&
+ (
+ cd "$subtree_test_count" &&
+ git fetch ./"sub proj" master &&
+ git subtree add --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub1 &&
+ test_create_commit "$subtree_test_count" main2 &&
+ test_create_commit "$subtree_test_count/sub proj" sub2 &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub2 &&
+ (
+ cd $subtree_test_count/"sub proj" &&
+ git branch sub-branch-1 &&
+ cd .. &&
+ git fetch ./"sub proj" master &&
+ git subtree merge --prefix="sub dir" FETCH_HEAD
+ ) &&
+ test_create_commit "$subtree_test_count" "sub dir"/main-sub3 &&
+ (
+ cd "$subtree_test_count" &&
+ git subtree push ./"sub proj" --prefix "sub dir" sub-branch-1 &&
+ cd ./"sub proj" &&
+ git checkout sub-branch-1 &&
+ check_equal "$(last_commit_message)" "sub dir/main-sub3"
+ )
'
test_done
exactly the right subtree structure, rather than using
subtree merge...)
- add a 'push' subcommand to parallel 'pull'
-
add a 'log' subcommand to see what's new in a subtree?
add to-submodule and from-submodule commands
int main(int argc, const char **argv)
{
const char *socket_path;
+ int ignore_sighup = 0;
static const char *usage[] = {
"git-credential-cache--daemon [opts] <socket_path>",
NULL
OPT_END()
};
+ git_config_get_bool("credentialcache.ignoresighup", &ignore_sighup);
+
argc = parse_options(argc, argv, NULL, options, usage, 0);
socket_path = argv[0];
check_socket_directory(socket_path);
register_tempfile(&socket_file, socket_path);
+
+ if (ignore_sighup)
+ signal(SIGHUP, SIG_IGN);
+
serve_cache(socket_path, debug);
delete_tempfile(&socket_file);
}
}
- if (verify_headers(buffer, size, &tag->object, options))
+ ret = verify_headers(buffer, size, &tag->object, options);
+ if (ret)
goto done;
if (!skip_prefix(buffer, "object ", &buffer)) {
start_timestamp=$(date '+%s')
fi
+if test -n "$filter_index" ||
+ test -n "$filter_tree" ||
+ test -n "$filter_subdir"
+then
+ need_index=t
+else
+ need_index=
+fi
+
while read commit parents; do
git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
case "$filter_subdir" in
"")
- GIT_ALLOW_NULL_SHA1=1 git read-tree -i -m $commit
+ if test -n "$need_index"
+ then
+ GIT_ALLOW_NULL_SHA1=1 git read-tree -i -m $commit
+ fi
;;
*)
# The commit may not have the subdirectory at all
die "tree filter failed: $filter_tree"
(
- git diff-index -r --name-only --ignore-submodules $commit &&
+ git diff-index -r --name-only --ignore-submodules $commit -- &&
git ls-files --others
) > "$tempdir"/tree-state || exit
git update-index --add --replace --remove --stdin \
} <../commit |
eval "$filter_msg" > ../message ||
die "msg filter failed: $filter_msg"
+
+ if test -n "$need_index"
+ then
+ tree=$(git write-tree)
+ else
+ tree="$commit^{tree}"
+ fi
workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
- $(git write-tree) $parentstr < ../message > ../map/$commit ||
+ "$tree" $parentstr < ../message > ../map/$commit ||
die "could not write rewritten commit"
done <../revs
# assume it failed because @... was invalid changelist
return True
-def system(cmd):
+def system(cmd, ignore_error=False):
expand = isinstance(cmd,basestring)
if verbose:
sys.stderr.write("executing %s\n" % str(cmd))
retcode = subprocess.call(cmd, shell=expand)
- if retcode:
+ if retcode and not ignore_error:
raise CalledProcessError(retcode, cmd)
+ return retcode
+
def p4_system(cmd):
"""Specifically invoke p4 as the system command. """
real_cmd = p4_build_cmd(cmd)
return clientPath
def currentGitBranch():
- return read_pipe("git name-rev HEAD").split(" ")[1].strip()
+ retcode = system(["git", "symbolic-ref", "-q", "HEAD"], ignore_error=True)
+ if retcode != 0:
+ # on a detached head
+ return None
+ else:
+ return read_pipe(["git", "name-rev", "HEAD"]).split(" ")[1].strip()
def isValidGitDir(path):
if (os.path.exists(path + "/HEAD")
#
# Let the user edit the change description, then submit it.
#
- if self.edit_template(fileName):
- # read the edited message and submit
- ret = True
- tmpFile = open(fileName, "rb")
- message = tmpFile.read()
- tmpFile.close()
- if self.isWindows:
- message = message.replace("\r\n", "\n")
- submitTemplate = message[:message.index(separatorLine)]
- p4_write_pipe(['submit', '-i'], submitTemplate)
-
- if self.preserveUser:
- if p4User:
- # Get last changelist number. Cannot easily get it from
- # the submit command output as the output is
- # unmarshalled.
- changelist = self.lastP4Changelist()
- self.modifyChangelistUser(changelist, p4User)
-
- # The rename/copy happened by applying a patch that created a
- # new file. This leaves it writable, which confuses p4.
- for f in pureRenameCopy:
- p4_sync(f, "-f")
+ submitted = False
- else:
+ try:
+ if self.edit_template(fileName):
+ # read the edited message and submit
+ tmpFile = open(fileName, "rb")
+ message = tmpFile.read()
+ tmpFile.close()
+ if self.isWindows:
+ message = message.replace("\r\n", "\n")
+ submitTemplate = message[:message.index(separatorLine)]
+ p4_write_pipe(['submit', '-i'], submitTemplate)
+
+ if self.preserveUser:
+ if p4User:
+ # Get last changelist number. Cannot easily get it from
+ # the submit command output as the output is
+ # unmarshalled.
+ changelist = self.lastP4Changelist()
+ self.modifyChangelistUser(changelist, p4User)
+
+ # The rename/copy happened by applying a patch that created a
+ # new file. This leaves it writable, which confuses p4.
+ for f in pureRenameCopy:
+ p4_sync(f, "-f")
+ submitted = True
+
+ finally:
# skip this patch
- ret = False
- print "Submission cancelled, undoing p4 changes."
- for f in editedFiles:
- p4_revert(f)
- for f in filesToAdd:
- p4_revert(f)
- os.remove(f)
- for f in filesToDelete:
- p4_revert(f)
+ if not submitted:
+ print "Submission cancelled, undoing p4 changes."
+ for f in editedFiles:
+ p4_revert(f)
+ for f in filesToAdd:
+ p4_revert(f)
+ os.remove(f)
+ for f in filesToDelete:
+ p4_revert(f)
os.remove(fileName)
- return ret
+ return submitted
# Export git tags as p4 labels. Create a p4 label and then tag
# with that.
def run(self, args):
if len(args) == 0:
self.master = currentGitBranch()
- if len(self.master) == 0 or not gitBranchExists("refs/heads/%s" % self.master):
- die("Detecting current git branch failed!")
elif len(args) == 1:
self.master = args[0]
if not branchExists(self.master):
else:
return False
- allowSubmit = gitConfig("git-p4.allowSubmit")
- if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","):
- die("%s is not in git-p4.allowSubmit" % self.master)
+ if self.master:
+ allowSubmit = gitConfig("git-p4.allowSubmit")
+ if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","):
+ die("%s is not in git-p4.allowSubmit" % self.master)
[upstream, settings] = findUpstreamBranchPoint()
self.depotPath = settings['depot-paths'][0]
self.check()
commits = []
- for line in read_pipe_lines(["git", "rev-list", "--no-merges", "%s..%s" % (self.origin, self.master)]):
+ if self.master:
+ commitish = self.master
+ else:
+ commitish = 'HEAD'
+
+ for line in read_pipe_lines(["git", "rev-list", "--no-merges", "%s..%s" % (self.origin, commitish)]):
commits.append(line.strip())
commits.reverse()
read -r command rest < "$todo"
mark_action_done
printf 'Executing: %s\n' "$rest"
- ${SHELL:-@SHELL_PATH@} -c "$rest" # Actual execution
+ "${SHELL:-@SHELL_PATH@}" -c "$rest" # Actual execution
status=$?
# Run in subshell because require_clean_work_tree can die.
dirty=f
sub usage {
print <<EOT;
git send-email [options] <file | directory | rev-list options >
+git send-email --dump-aliases
Composing:
--from <str> * Email From:
`git format-patch` ones.
--force * Send even if safety checks would prevent it.
+ Information:
+ --dump-aliases * Dump configured aliases and exit.
+
EOT
exit(1);
}
my $format_patch;
my $compose_filename;
my $force = 0;
+my $dump_aliases = 0;
# Handle interactive edition of files.
my $multiedit;
"smtpserveroption" => \@smtp_server_options,
"smtpuser" => \$smtp_authuser,
"smtppass" => \$smtp_authpass,
- "smtpsslcertpath" => \$smtp_ssl_cert_path,
"smtpdomain" => \$smtp_domain,
"smtpauth" => \$smtp_auth,
"to" => \@initial_to,
my %config_path_settings = (
"aliasesfile" => \@alias_files,
+ "smtpsslcertpath" => \$smtp_ssl_cert_path,
);
# Handle Uncouth Termination
my $help;
my $rc = GetOptions("h" => \$help,
+ "dump-aliases" => \$dump_aliases);
+usage() unless $rc;
+die "--dump-aliases incompatible with other options\n"
+ if !$help and $dump_aliases and @ARGV;
+$rc = GetOptions(
"sender|from=s" => \$sender,
"in-reply-to=s" => \$initial_reply_to,
"subject=s" => \$initial_subject,
}
}
+if ($dump_aliases) {
+ print "$_\n" for (sort keys %aliases);
+ exit(0);
+}
+
# is_format_patch_arg($f) returns 0 if $f names a patch, or 1 if
# $f is a revision list specification to be passed to format-patch.
sub is_format_patch_arg {
return (SSL_verify_mode => SSL_VERIFY_PEER(),
SSL_ca_file => $smtp_ssl_cert_path);
} else {
- print STDERR "Not using SSL_VERIFY_PEER because the CA path does not exist.\n";
- return (SSL_verify_mode => SSL_VERIFY_NONE());
+ die "CA path \"$smtp_ssl_cert_path\" does not exist";
}
}
#endif
#if LIBCURL_VERSION_NUM >= 0x070908
if (!strcmp("http.sslcapath", var))
- return git_config_string(&ssl_capath, var, value);
+ return git_config_pathname(&ssl_capath, var, value);
#endif
if (!strcmp("http.sslcainfo", var))
- return git_config_string(&ssl_cainfo, var, value);
+ return git_config_pathname(&ssl_cainfo, var, value);
if (!strcmp("http.sslcertpasswordprotected", var)) {
ssl_cert_password_required = git_config_bool(var, value);
return 0;
if (curl_http_proxy) {
curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
+#if LIBCURL_VERSION_NUM >= 0x071800
+ if (starts_with(curl_http_proxy, "socks5"))
+ curl_easy_setopt(result,
+ CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+ else if (starts_with(curl_http_proxy, "socks4a"))
+ curl_easy_setopt(result,
+ CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A);
+ else if (starts_with(curl_http_proxy, "socks"))
+ curl_easy_setopt(result,
+ CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+#endif
}
#if LIBCURL_VERSION_NUM >= 0x070a07
curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
if (prev_posn>0) {
if (http_is_verbose)
fprintf(stderr,
- "Resuming fetch of pack %s at byte %ld\n",
- sha1_to_hex(target->sha1), prev_posn);
+ "Resuming fetch of pack %s at byte %"PRIuMAX"\n",
+ sha1_to_hex(target->sha1), (uintmax_t)prev_posn);
http_opt_request_remainder(preq->slot->curl, prev_posn);
}
if (prev_posn>0) {
if (http_is_verbose)
fprintf(stderr,
- "Resuming fetch of object %s at byte %ld\n",
- hex, prev_posn);
+ "Resuming fetch of object %s at byte %"PRIuMAX"\n",
+ hex, (uintmax_t)prev_posn);
http_opt_request_remainder(freq->slot->curl, prev_posn);
}
#include "color.h"
#include "utf8.h"
-static int parse_options_usage(struct parse_opt_ctx_t *ctx,
- const char * const *usagestr,
- const struct option *opts, int err);
-
#define OPT_SHORT 1
#define OPT_UNSET 2
const struct option *options, int flags)
{
memset(ctx, 0, sizeof(*ctx));
- ctx->argc = argc - 1;
+ ctx->argc = ctx->total = argc - 1;
ctx->argv = argv + 1;
ctx->out = argv;
ctx->prefix = prefix;
const char * const usagestr[])
{
int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
+ int err = 0;
/* we must reset ->opt, unknown short option leave it dangling */
ctx->opt = NULL;
continue;
}
+ /* lone -h asks for help */
+ if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
+ goto show_usage;
+
if (arg[1] != '-') {
ctx->opt = arg + 1;
- if (internal_help && *ctx->opt == 'h')
- return parse_options_usage(ctx, usagestr, options, 0);
switch (parse_short_opt(ctx, options)) {
case -1:
- return parse_options_usage(ctx, usagestr, options, 1);
+ goto show_usage_error;
case -2:
if (ctx->opt)
check_typos(arg + 1, options);
+ if (internal_help && *ctx->opt == 'h')
+ goto show_usage;
goto unknown;
}
if (ctx->opt)
check_typos(arg + 1, options);
while (ctx->opt) {
- if (internal_help && *ctx->opt == 'h')
- return parse_options_usage(ctx, usagestr, options, 0);
switch (parse_short_opt(ctx, options)) {
case -1:
- return parse_options_usage(ctx, usagestr, options, 1);
+ goto show_usage_error;
case -2:
+ if (internal_help && *ctx->opt == 'h')
+ goto show_usage;
+
/* fake a short option thing to hide the fact that we may have
* started to parse aggregated stuff
*
if (internal_help && !strcmp(arg + 2, "help-all"))
return usage_with_options_internal(ctx, usagestr, options, 1, 0);
if (internal_help && !strcmp(arg + 2, "help"))
- return parse_options_usage(ctx, usagestr, options, 0);
+ goto show_usage;
switch (parse_long_opt(ctx, arg + 2, options)) {
case -1:
- return parse_options_usage(ctx, usagestr, options, 1);
+ goto show_usage_error;
case -2:
goto unknown;
}
ctx->opt = NULL;
}
return PARSE_OPT_DONE;
+
+ show_usage_error:
+ err = 1;
+ show_usage:
+ return usage_with_options_internal(ctx, usagestr, options, 0, err);
}
int parse_options_end(struct parse_opt_ctx_t *ctx)
usage_with_options(usagestr, options);
}
-static int parse_options_usage(struct parse_opt_ctx_t *ctx,
- const char * const *usagestr,
- const struct option *opts, int err)
-{
- return usage_with_options_internal(ctx, usagestr, opts, 0, err);
-}
-
#undef opterror
int opterror(const struct option *opt, const char *reason, int flags)
{
struct parse_opt_ctx_t {
const char **argv;
const char **out;
- int argc, cpidx;
+ int argc, cpidx, total;
const char *opt;
int flags;
const char *prefix;
strbuf_setlen(&sb, len);
strbuf_addstr(&sb, path);
if (file_exists(sb.buf))
- report_garbage("unused in linked checkout", sb.buf);
+ report_garbage(PACKDIR_FILE_GARBAGE, sb.buf);
}
strbuf_release(&sb);
}
sub mkemptydirs {
my ($self, $r) = @_;
+ # add/remove/collect a paths table
+ #
+ # Paths are split into a tree of nodes, stored as a hash of hashes.
+ #
+ # Each node contains a 'path' entry for the path (if any) associated
+ # with that node and a 'children' entry for any nodes under that
+ # location.
+ #
+ # Removing a path requires a hash lookup for each component then
+ # dropping that node (and anything under it), which is substantially
+ # faster than a grep slice into a single hash of paths for large
+ # numbers of paths.
+ #
+ # For a large (200K) number of empty_dir directives this reduces
+ # scanning time to 3 seconds vs 10 minutes for grep+delete on a single
+ # hash of paths.
+ sub add_path {
+ my ($paths_table, $path) = @_;
+ my $node_ref;
+
+ foreach my $x (split('/', $path)) {
+ if (!exists($paths_table->{$x})) {
+ $paths_table->{$x} = { children => {} };
+ }
+
+ $node_ref = $paths_table->{$x};
+ $paths_table = $paths_table->{$x}->{children};
+ }
+
+ $node_ref->{path} = $path;
+ }
+
+ sub remove_path {
+ my ($paths_table, $path) = @_;
+ my $nodes_ref;
+ my $node_name;
+
+ foreach my $x (split('/', $path)) {
+ if (!exists($paths_table->{$x})) {
+ return;
+ }
+
+ $nodes_ref = $paths_table;
+ $node_name = $x;
+
+ $paths_table = $paths_table->{$x}->{children};
+ }
+
+ delete($nodes_ref->{$node_name});
+ }
+
+ sub collect_paths {
+ my ($paths_table, $paths_ref) = @_;
+
+ foreach my $v (values %$paths_table) {
+ my $p = $v->{path};
+ my $c = $v->{children};
+
+ collect_paths($c, $paths_ref);
+
+ if (defined($p)) {
+ push(@$paths_ref, $p);
+ }
+ }
+ }
+
sub scan {
- my ($r, $empty_dirs, $line) = @_;
+ my ($r, $paths_table, $line) = @_;
if (defined $r && $line =~ /^r(\d+)$/) {
return 0 if $1 > $r;
} elsif ($line =~ /^ \+empty_dir: (.+)$/) {
- $empty_dirs->{$1} = 1;
+ add_path($paths_table, $1);
} elsif ($line =~ /^ \-empty_dir: (.+)$/) {
- my @d = grep {m[^\Q$1\E(/|$)]} (keys %$empty_dirs);
- delete @$empty_dirs{@d};
+ remove_path($paths_table, $1);
}
1; # continue
};
- my %empty_dirs = ();
+ my @empty_dirs;
+ my %paths_table;
+
my $gz_file = "$self->{dir}/unhandled.log.gz";
if (-f $gz_file) {
if (!can_compress()) {
die "Unable to open $gz_file: $!\n";
my $line;
while ($gz->gzreadline($line) > 0) {
- scan($r, \%empty_dirs, $line) or last;
+ scan($r, \%paths_table, $line) or last;
}
$gz->gzclose;
}
if (open my $fh, '<', "$self->{dir}/unhandled.log") {
binmode $fh or croak "binmode: $!";
while (<$fh>) {
- scan($r, \%empty_dirs, $_) or last;
+ scan($r, \%paths_table, $_) or last;
}
close $fh;
}
+ collect_paths(\%paths_table, \@empty_dirs);
my $strip = qr/\A\Q@{[$self->path]}\E(?:\/|$)/;
- foreach my $d (sort keys %empty_dirs) {
+ foreach my $d (sort @empty_dirs) {
$d = uri_decode($d);
$d =~ s/$strip//;
next unless length($d);
int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *p, unsigned long n);
int ppc_SHA1_Final(unsigned char *hash, ppc_SHA_CTX *c);
-#define git_SHA_CTX ppc_SHA_CTX
-#define git_SHA1_Init ppc_SHA1_Init
-#define git_SHA1_Update ppc_SHA1_Update
-#define git_SHA1_Final ppc_SHA1_Final
+#define platform_SHA_CTX ppc_SHA_CTX
+#define platform_SHA1_Init ppc_SHA1_Init
+#define platform_SHA1_Update ppc_SHA1_Update
+#define platform_SHA1_Final ppc_SHA1_Final
return 0;
}
-int ref_is_hidden(const char *refname)
+int ref_is_hidden(const char *refname, const char *refname_full)
{
int i;
return 0;
for (i = hide_refs->nr - 1; i >= 0; i--) {
const char *match = hide_refs->items[i].string;
+ const char *subject;
int neg = 0;
int len;
match++;
}
- if (!starts_with(refname, match))
+ if (*match == '^') {
+ subject = refname_full;
+ match++;
+ } else {
+ subject = refname;
+ }
+
+ /* refname can be NULL when namespaces are used. */
+ if (!subject || !starts_with(subject, match))
continue;
len = strlen(match);
- if (!refname[len] || refname[len] == '/')
+ if (!subject[len] || subject[len] == '/')
return !neg;
}
return 0;
extern int parse_hide_refs_config(const char *var, const char *value, const char *);
-extern int ref_is_hidden(const char *);
+/*
+ * Check whether a ref is hidden. If no namespace is set, both the first and
+ * the second parameter point to the full ref name. If a namespace is set and
+ * the ref is inside that namespace, the first parameter is a pointer to the
+ * name of the ref with the namespace prefix removed. If a namespace is set and
+ * the ref is outside that namespace, the first parameter is NULL. The second
+ * parameter always points to the full ref name.
+ */
+extern int ref_is_hidden(const char *, const char *);
enum ref_type {
REF_TYPE_PER_WORKTREE,
packed_git = pack;
}
-void (*report_garbage)(const char *desc, const char *path);
+void (*report_garbage)(unsigned seen_bits, const char *path);
static void report_helper(const struct string_list *list,
int seen_bits, int first, int last)
{
- const char *msg;
- switch (seen_bits) {
- case 0:
- msg = "no corresponding .idx or .pack";
- break;
- case 1:
- msg = "no corresponding .idx";
- break;
- case 2:
- msg = "no corresponding .pack";
- break;
- default:
+ if (seen_bits == (PACKDIR_FILE_PACK|PACKDIR_FILE_IDX))
return;
- }
+
for (; first < last; first++)
- report_garbage(msg, list->items[first].string);
+ report_garbage(seen_bits, list->items[first].string);
}
static void report_pack_garbage(struct string_list *list)
if (baselen == -1) {
const char *dot = strrchr(path, '.');
if (!dot) {
- report_garbage("garbage found", path);
+ report_garbage(PACKDIR_FILE_GARBAGE, path);
continue;
}
baselen = dot - path + 1;
ends_with(de->d_name, ".keep"))
string_list_append(&garbage, path.buf);
else
- report_garbage("garbage found", path.buf);
+ report_garbage(PACKDIR_FILE_GARBAGE, path.buf);
}
closedir(dir);
report_pack_garbage(&garbage);
check_count A 2
'
+test_expect_success 'blame by tag objects' '
+ git tag -m "test tag" testTag &&
+ git tag -m "test tag #2" testTag2 testTag &&
+ check_count -h testTag A 2 &&
+ check_count -h testTag2 A 2
+'
+
test_expect_success 'setup B lines' '
echo "2A quick brown fox jumps over the" >>file &&
echo "lazy dog" >>file &&
# a subdirectory called "$git"
TEST_NO_CREATE_REPO=NoThanks
+# Some operations require multiple attempts to be successful. Define
+# here the maximal retry timeout in seconds.
+RETRY_TIMEOUT=60
+
+# Sometimes p4d seems to hang. Terminate the p4d process automatically after
+# the defined timeout in seconds.
+P4D_TIMEOUT=300
+
. ./test-lib.sh
if ! test_have_prereq PYTHON
echo "$path"
}
+# On Solaris the 'date +%s' function is not supported and therefore we
+# need this replacement.
+# Attention: This function is not safe again against time offset updates
+# at runtime (e.g. via NTP). The 'clock_gettime(CLOCK_MONOTONIC)'
+# function could fix that but it is not in Python until 3.3.
+time_in_seconds() {
+ python -c 'import time; print int(time.time())'
+}
+
# Try to pick a unique port: guess a large number, then hope
# no more than one of each test is running.
#
git="$TRASH_DIRECTORY/git"
pidfile="$TRASH_DIRECTORY/p4d.pid"
+# Sometimes "prove" seems to hang on exit because p4d is still running
+cleanup() {
+ if test -f "$pidfile"
+ then
+ kill -9 $(cat "$pidfile") 2>/dev/null && exit 255
+ fi
+}
+trap cleanup EXIT
+
# git p4 submit generates a temp file, which will
# not get cleaned up if the submission fails. Don't
# clutter up /tmp on the test machine.
# will be caught with the "kill -0" check below.
i=${P4D_START_PATIENCE:-300}
pid=$(cat "$pidfile")
+
+ timeout=$(($(time_in_seconds) + $P4D_TIMEOUT))
+ while true
+ do
+ if test $(time_in_seconds) -gt $timeout
+ then
+ kill -9 $pid
+ exit 1
+ fi
+ sleep 1
+ done &
+ watchdog_pid=$!
+
ready=
while test $i -gt 0
do
EOF
}
+retry_until_success() {
+ timeout=$(($(time_in_seconds) + $RETRY_TIMEOUT))
+ until "$@" 2>/dev/null || test $(time_in_seconds) -gt $timeout
+ do
+ sleep 1
+ done
+}
+
+retry_until_fail() {
+ timeout=$(($(time_in_seconds) + $RETRY_TIMEOUT))
+ until ! "$@" 2>/dev/null || test $(time_in_seconds) -gt $timeout
+ do
+ sleep 1
+ done
+}
+
kill_p4d() {
pid=$(cat "$pidfile")
- # it had better exist for the first kill
- kill $pid &&
- for i in 1 2 3 4 5 ; do
- kill $pid >/dev/null 2>&1 || break
- sleep 1
- done &&
+ retry_until_fail kill $pid
+ retry_until_fail kill -9 $pid
# complain if it would not die
test_must_fail kill $pid >/dev/null 2>&1 &&
- rm -rf "$db" "$cli" "$pidfile"
+ rm -rf "$db" "$cli" "$pidfile" &&
+ retry_until_fail kill -9 $watchdog_pid
}
cleanup_git() {
- rm -rf "$git" &&
- mkdir "$git"
+ retry_until_success rm -r "$git"
+ test_must_fail test -d "$git" &&
+ retry_until_success mkdir "$git"
}
marshal_dump() {
--- /dev/null
+#!/bin/sh
+
+test_description='performance of filter-branch'
+. ./perf-lib.sh
+
+test_perf_default_repo
+test_checkout_worktree
+
+test_expect_success 'mark bases for tests' '
+ git tag -f tip &&
+ git tag -f base HEAD~100
+'
+
+test_perf 'noop filter' '
+ git checkout --detach tip &&
+ git filter-branch -f base..HEAD
+'
+
+test_done
grep "error in commit $new.*integer overflow" out
'
+test_expect_success 'commit with NUL in header' '
+ git cat-file commit HEAD >basis &&
+ sed "s/author ./author Q/" <basis | q_to_nul >commit-NUL-header &&
+ new=$(git hash-object -t commit -w --stdin <commit-NUL-header) &&
+ test_when_finished "remove_object $new" &&
+ git update-ref refs/heads/bogus "$new" &&
+ test_when_finished "git update-ref -d refs/heads/bogus" &&
+ test_must_fail git fsck 2>out &&
+ cat out &&
+ grep "error in commit $new.*unterminated header: NUL at offset" out
+'
+
test_expect_success 'malformatted tree object' '
test_when_finished "git update-ref -d refs/tags/wrong" &&
test_when_finished "remove_object \$T" &&
grep "error in tag .*: invalid author/committer" out
'
+test_expect_success 'tag with NUL in header' '
+ sha=$(git rev-parse HEAD) &&
+ q_to_nul >tag-NUL-header <<-EOF &&
+ object $sha
+ type commit
+ tag contains-Q-in-header
+ tagger T A Gger <tagger@example.com> 1234567890 -0000
+
+ This is an invalid tag.
+ EOF
+
+ tag=$(git hash-object --literally -t tag -w --stdin <tag-NUL-header) &&
+ test_when_finished "remove_object $tag" &&
+ echo $tag >.git/refs/tags/wrong &&
+ test_when_finished "git update-ref -d refs/tags/wrong" &&
+ test_must_fail git fsck --tags 2>out &&
+ cat out &&
+ grep "error in tag $tag.*unterminated header: NUL at offset" out
+'
+
test_expect_success 'cleaned up' '
git fsck >actual 2>&1 &&
test_cmp empty actual
test_expect_success 'garbage report in count-objects -v' '
test_when_finished "rm -f .git/objects/pack/fake*" &&
+ test_when_finished "rm -f .git/objects/pack/foo*" &&
: >.git/objects/pack/foo &&
: >.git/objects/pack/foo.bar &&
: >.git/objects/pack/foo.keep &&
test_cmp expected actual
'
+test_expect_success 'clean pack garbage with gc' '
+ test_when_finished "rm -f .git/objects/pack/fake*" &&
+ test_when_finished "rm -f .git/objects/pack/foo*" &&
+ : >.git/objects/pack/foo.keep &&
+ : >.git/objects/pack/foo.pack &&
+ : >.git/objects/pack/fake.idx &&
+ : >.git/objects/pack/fake2.keep &&
+ : >.git/objects/pack/fake2.idx &&
+ : >.git/objects/pack/fake3.keep &&
+ git gc &&
+ git count-objects -v 2>stderr &&
+ grep "^warning:" stderr | sort >actual &&
+ cat >expected <<\EOF &&
+warning: no corresponding .idx or .pack: .git/objects/pack/fake3.keep
+warning: no corresponding .idx: .git/objects/pack/foo.keep
+warning: no corresponding .idx: .git/objects/pack/foo.pack
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'prune .git/shallow' '
SHA1=`echo hi|git commit-tree HEAD^{tree}` &&
echo $SHA1 >.git/shallow &&
)
'
+test_expect_success 'hide namespaced refs with transfer.hideRefs' '
+ GIT_NAMESPACE=namespace \
+ git -C pushee -c transfer.hideRefs=refs/tags \
+ ls-remote "ext::git %s ." >actual &&
+ printf "$commit1\trefs/heads/master\n" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'check that transfer.hideRefs does not match unstripped refs' '
+ GIT_NAMESPACE=namespace \
+ git -C pushee -c transfer.hideRefs=refs/namespaces/namespace/refs/tags \
+ ls-remote "ext::git %s ." >actual &&
+ printf "$commit1\trefs/heads/master\n" >expected &&
+ printf "$commit0\trefs/tags/0\n" >>expected &&
+ printf "$commit1\trefs/tags/1\n" >>expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'hide full refs with transfer.hideRefs' '
+ GIT_NAMESPACE=namespace \
+ git -C pushee -c transfer.hideRefs="^refs/namespaces/namespace/refs/tags" \
+ ls-remote "ext::git %s ." >actual &&
+ printf "$commit1\trefs/heads/master\n" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'try to update a hidden ref' '
+ test_config -C pushee transfer.hideRefs refs/heads/master &&
+ test_must_fail git -C original push pushee-namespaced master
+'
+
+test_expect_success 'try to update a ref that is not hidden' '
+ test_config -C pushee transfer.hideRefs refs/namespaces/namespace/refs/heads/master &&
+ git -C original push pushee-namespaced master
+'
+
+test_expect_success 'try to update a hidden full ref' '
+ test_config -C pushee transfer.hideRefs "^refs/namespaces/namespace/refs/heads/master" &&
+ test_must_fail git -C original push pushee-namespaced master
+'
+
test_done
diff expected actual
'
-# Test that filling pipe buffers doesn't cause failure
-# Too slow to leave enabled for general use
-if false
-then
- printf 'parent1\nrepo1\n' >expected
- nr=1000
- while test $nr -lt 2000
- do
- nr=$(( $nr + 1 ))
- git branch b/$nr $COMMIT3
- echo "refs/heads/b/$nr $COMMIT3 refs/heads/b/$nr $_z40" >>expected
- done
-
- test_expect_success 'push many refs' '
- git push parent1 "refs/heads/b/*:refs/heads/b/*" &&
- diff expected actual
- '
-fi
+test_expect_success 'set up many-ref tests' '
+ {
+ nr=1000
+ while test $nr -lt 2000
+ do
+ nr=$(( $nr + 1 ))
+ echo "create refs/heads/b/$nr $COMMIT3"
+ done
+ } | git update-ref --stdin
+'
+
+test_expect_success 'sigpipe does not cause pre-push hook failure' '
+ echo "exit 0" | write_script "$HOOK" &&
+ git push parent1 "refs/heads/b/*:refs/heads/b/*"
+'
test_done
'
test_proto "host:path" ssh "remote:repo.git"
-test_proto "ssh://" ssh "ssh://remote/$PWD/remote/repo.git"
-test_proto "git+ssh://" ssh "git+ssh://remote/$PWD/remote/repo.git"
+test_proto "ssh://" ssh "ssh://remote$PWD/remote/repo.git"
+test_proto "git+ssh://" ssh "git+ssh://remote$PWD/remote/repo.git"
test_done
test_cmp expect actual
'
+test_expect_success 'tree-filter deals with object name vs pathname ambiguity' '
+ test_when_finished "git reset --hard original" &&
+ ambiguous=$(git rev-list -1 HEAD) &&
+ git filter-branch --tree-filter "mv file.t $ambiguous" HEAD^.. &&
+ git show HEAD:$ambiguous
+'
+
test_done
grep "^!someone@example\.org!$" commandline1
'
+test_dump_aliases () {
+ msg="$1" && shift &&
+ filetype="$1" && shift &&
+ printf '%s\n' "$@" >expect &&
+ cat >.tmp-email-aliases &&
+
+ test_expect_success $PREREQ "$msg" '
+ clean_fake_sendmail && rm -fr outdir &&
+ git config --replace-all sendemail.aliasesfile \
+ "$(pwd)/.tmp-email-aliases" &&
+ git config sendemail.aliasfiletype "$filetype" &&
+ git send-email --dump-aliases 2>errors >actual &&
+ test_cmp expect actual
+ '
+}
+
+test_dump_aliases '--dump-aliases sendmail format' \
+ 'sendmail' \
+ 'abgroup' \
+ 'alice' \
+ 'bcgrp' \
+ 'bob' \
+ 'chloe' <<-\EOF
+ alice: Alice W Land <awol@example.com>
+ bob: Robert Bobbyton <bob@example.com>
+ chloe: chloe@example.com
+ abgroup: alice, bob
+ bcgrp: bob, chloe, Other <o@example.com>
+ EOF
+
+test_dump_aliases '--dump-aliases mutt format' \
+ 'mutt' \
+ 'alice' \
+ 'bob' \
+ 'chloe' \
+ 'donald' <<-\EOF
+ alias alice Alice W Land <awol@example.com>
+ alias donald Donald C Carlton <donc@example.com>
+ alias bob Robert Bobbyton <bob@example.com>
+ alias chloe chloe@example.com
+ EOF
+
+test_dump_aliases '--dump-aliases mailrc format' \
+ 'mailrc' \
+ 'alice' \
+ 'bob' \
+ 'chloe' \
+ 'eve' <<-\EOF
+ alias alice Alice W Land <awol@example.com>
+ alias eve Eve <eve@example.com>
+ alias bob Robert Bobbyton <bob@example.com>
+ alias chloe chloe@example.com
+ EOF
+
+test_dump_aliases '--dump-aliases pine format' \
+ 'pine' \
+ 'alice' \
+ 'bob' \
+ 'chloe' \
+ 'eve' <<-\EOF
+ alice Alice W Land <awol@example.com>
+ eve Eve <eve@example.com>
+ bob Robert Bobbyton <bob@example.com>
+ chloe chloe@example.com
+ EOF
+
+test_dump_aliases '--dump-aliases gnus format' \
+ 'gnus' \
+ 'alice' \
+ 'bob' \
+ 'chloe' \
+ 'eve' <<-\EOF
+ (define-mail-alias "alice" "awol@example.com")
+ (define-mail-alias "eve" "eve@example.com")
+ (define-mail-alias "bob" "bob@example.com")
+ (define-mail-alias "chloe" "chloe@example.com")
+ EOF
+
+test_expect_success '--dump-aliases must be used alone' '
+ test_must_fail git send-email --dump-aliases --to=janice@example.com -1 refs/heads/accounting
+'
+
test_sendmail_aliases () {
msg="$1" && shift &&
expect="$@" &&
file6_data='#!/bin/sh
echo "$@"'
->empty
-
###
### series A
###
-test_tick
-
test_expect_success 'empty stream succeeds' '
git fast-import </dev/null
'
-cat >input <<INPUT_END
-blob
-mark :2
-data <<EOF
-$file2_data
-EOF
-
-blob
-mark :3
-data <<END
-$file3_data
-END
-
-blob
-mark :4
-data $file4_len
-$file4_data
-commit refs/heads/master
-mark :5
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-initial
-COMMIT
-
-M 644 :2 file2
-M 644 :3 file3
-M 755 :4 file4
-
-tag series-A
-from :5
-data <<EOF
-An annotated tag without a tagger
-EOF
-
-tag series-A-blob
-from :3
-data <<EOF
-An annotated tag that annotates a blob.
-EOF
-
-INPUT_END
-test_expect_success \
- 'A: create pack from stdin' \
- 'git fast-import --export-marks=marks.out <input &&
- git whatchanged master'
+test_expect_success 'A: create pack from stdin' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ blob
+ mark :2
+ data <<EOF
+ $file2_data
+ EOF
+
+ blob
+ mark :3
+ data <<END
+ $file3_data
+ END
+
+ blob
+ mark :4
+ data $file4_len
+ $file4_data
+ commit refs/heads/master
+ mark :5
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ initial
+ COMMIT
+
+ M 644 :2 file2
+ M 644 :3 file3
+ M 755 :4 file4
+
+ tag series-A
+ from :5
+ data <<EOF
+ An annotated tag without a tagger
+ EOF
+
+ tag series-A-blob
+ from :3
+ data <<EOF
+ An annotated tag that annotates a blob.
+ EOF
+
+ INPUT_END
+ git fast-import --export-marks=marks.out <input &&
+ git whatchanged master
+'
test_expect_success 'A: verify pack' '
verify_packs
'
-cat >expect <<EOF
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-initial
-EOF
-test_expect_success \
- 'A: verify commit' \
- 'git cat-file commit master | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect <<EOF
-100644 blob file2
-100644 blob file3
-100755 blob file4
-EOF
-test_expect_success \
- 'A: verify tree' \
- 'git cat-file -p master^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
- test_cmp expect actual'
-
-echo "$file2_data" >expect
-test_expect_success \
- 'A: verify file2' \
- 'git cat-file blob master:file2 >actual && test_cmp expect actual'
-
-echo "$file3_data" >expect
-test_expect_success \
- 'A: verify file3' \
- 'git cat-file blob master:file3 >actual && test_cmp expect actual'
-
-printf "$file4_data" >expect
-test_expect_success \
- 'A: verify file4' \
- 'git cat-file blob master:file4 >actual && test_cmp expect actual'
-
-cat >expect <<EOF
-object $(git rev-parse refs/heads/master)
-type commit
-tag series-A
-
-An annotated tag without a tagger
-EOF
+test_expect_success 'A: verify commit' '
+ cat >expect <<-EOF &&
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+ initial
+ EOF
+ git cat-file commit master | sed 1d >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'A: verify tree' '
+ cat >expect <<-EOF &&
+ 100644 blob file2
+ 100644 blob file3
+ 100755 blob file4
+ EOF
+ git cat-file -p master^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'A: verify file2' '
+ echo "$file2_data" >expect &&
+ git cat-file blob master:file2 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'A: verify file3' '
+ echo "$file3_data" >expect &&
+ git cat-file blob master:file3 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'A: verify file4' '
+ printf "$file4_data" >expect &&
+ git cat-file blob master:file4 >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'A: verify tag/series-A' '
+ cat >expect <<-EOF &&
+ object $(git rev-parse refs/heads/master)
+ type commit
+ tag series-A
+
+ An annotated tag without a tagger
+ EOF
git cat-file tag tags/series-A >actual &&
test_cmp expect actual
'
-cat >expect <<EOF
-object $(git rev-parse refs/heads/master:file3)
-type blob
-tag series-A-blob
-
-An annotated tag that annotates a blob.
-EOF
test_expect_success 'A: verify tag/series-A-blob' '
+ cat >expect <<-EOF &&
+ object $(git rev-parse refs/heads/master:file3)
+ type blob
+ tag series-A-blob
+
+ An annotated tag that annotates a blob.
+ EOF
git cat-file tag tags/series-A-blob >actual &&
test_cmp expect actual
'
-cat >expect <<EOF
-:2 `git rev-parse --verify master:file2`
-:3 `git rev-parse --verify master:file3`
-:4 `git rev-parse --verify master:file4`
-:5 `git rev-parse --verify master^0`
-EOF
-test_expect_success \
- 'A: verify marks output' \
- 'test_cmp expect marks.out'
+test_expect_success 'A: verify marks output' '
+ cat >expect <<-EOF &&
+ :2 `git rev-parse --verify master:file2`
+ :3 `git rev-parse --verify master:file3`
+ :4 `git rev-parse --verify master:file4`
+ :5 `git rev-parse --verify master^0`
+ EOF
+ test_cmp expect marks.out
+'
-test_expect_success \
- 'A: verify marks import' \
- 'git fast-import \
+test_expect_success 'A: verify marks import' '
+ git fast-import \
--import-marks=marks.out \
--export-marks=marks.new \
</dev/null &&
- test_cmp expect marks.new'
-
-test_tick
-new_blob=$(echo testing | git hash-object --stdin)
-cat >input <<INPUT_END
-tag series-A-blob-2
-from $(git rev-parse refs/heads/master:file3)
-data <<EOF
-Tag blob by sha1.
-EOF
-
-blob
-mark :6
-data <<EOF
-testing
-EOF
-
-commit refs/heads/new_blob
-committer <> 0 +0000
-data 0
-M 644 :6 new_blob
-#pretend we got sha1 from fast-import
-ls "new_blob"
-
-tag series-A-blob-3
-from $new_blob
-data <<EOF
-Tag new_blob.
-EOF
-INPUT_END
-
-cat >expect <<EOF
-object $(git rev-parse refs/heads/master:file3)
-type blob
-tag series-A-blob-2
-
-Tag blob by sha1.
-object $new_blob
-type blob
-tag series-A-blob-3
-
-Tag new_blob.
-EOF
-
-test_expect_success \
- 'A: tag blob by sha1' \
- 'git fast-import <input &&
+ test_cmp expect marks.new
+'
+
+test_expect_success 'A: tag blob by sha1' '
+ test_tick &&
+ new_blob=$(echo testing | git hash-object --stdin) &&
+ cat >input <<-INPUT_END &&
+ tag series-A-blob-2
+ from $(git rev-parse refs/heads/master:file3)
+ data <<EOF
+ Tag blob by sha1.
+ EOF
+
+ blob
+ mark :6
+ data <<EOF
+ testing
+ EOF
+
+ commit refs/heads/new_blob
+ committer <> 0 +0000
+ data 0
+ M 644 :6 new_blob
+ #pretend we got sha1 from fast-import
+ ls "new_blob"
+
+ tag series-A-blob-3
+ from $new_blob
+ data <<EOF
+ Tag new_blob.
+ EOF
+ INPUT_END
+
+ cat >expect <<-EOF &&
+ object $(git rev-parse refs/heads/master:file3)
+ type blob
+ tag series-A-blob-2
+
+ Tag blob by sha1.
+ object $new_blob
+ type blob
+ tag series-A-blob-3
+
+ Tag new_blob.
+ EOF
+
+ git fast-import <input &&
git cat-file tag tags/series-A-blob-2 >actual &&
git cat-file tag tags/series-A-blob-3 >>actual &&
- test_cmp expect actual'
+ test_cmp expect actual
+'
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/verify--import-marks
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-recreate from :5
-COMMIT
+test_expect_success 'A: verify marks import does not crash' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/verify--import-marks
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ recreate from :5
+ COMMIT
-from :5
-M 755 :2 copy-of-file2
+ from :5
+ M 755 :2 copy-of-file2
-INPUT_END
-test_expect_success \
- 'A: verify marks import does not crash' \
- 'git fast-import --import-marks=marks.out <input &&
- git whatchanged verify--import-marks'
+ INPUT_END
+
+ git fast-import --import-marks=marks.out <input &&
+ git whatchanged verify--import-marks
+'
test_expect_success 'A: verify pack' '
verify_packs
'
-cat >expect <<EOF
-:000000 100755 0000000000000000000000000000000000000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 A copy-of-file2
-EOF
-git diff-tree -M -r master verify--import-marks >actual
-test_expect_success \
- 'A: verify diff' \
- 'compare_diff_raw expect actual &&
- test `git rev-parse --verify master:file2` \
- = `git rev-parse --verify verify--import-marks:copy-of-file2`'
-
-test_tick
-mt=$(git hash-object --stdin < /dev/null)
-: >input.blob
-: >marks.exp
-: >tree.exp
-
-cat >input.commit <<EOF
-commit refs/heads/verify--dump-marks
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-test the sparse array dumping routines with exponentially growing marks
-COMMIT
-EOF
-
-i=0
-l=4
-m=6
-n=7
-while test "$i" -lt 27; do
- cat >>input.blob <<EOF
-blob
-mark :$l
-data 0
-blob
-mark :$m
-data 0
-blob
-mark :$n
-data 0
-EOF
- echo "M 100644 :$l l$i" >>input.commit
- echo "M 100644 :$m m$i" >>input.commit
- echo "M 100644 :$n n$i" >>input.commit
-
- echo ":$l $mt" >>marks.exp
- echo ":$m $mt" >>marks.exp
- echo ":$n $mt" >>marks.exp
-
- printf "100644 blob $mt\tl$i\n" >>tree.exp
- printf "100644 blob $mt\tm$i\n" >>tree.exp
- printf "100644 blob $mt\tn$i\n" >>tree.exp
-
- l=$(($l + $l))
- m=$(($m + $m))
- n=$(($l + $n))
-
- i=$((1 + $i))
-done
-
-sort tree.exp > tree.exp_s
+test_expect_success 'A: verify diff' '
+ cat >expect <<-EOF &&
+ :000000 100755 0000000000000000000000000000000000000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 A copy-of-file2
+ EOF
+ git diff-tree -M -r master verify--import-marks >actual &&
+ compare_diff_raw expect actual &&
+ test `git rev-parse --verify master:file2` \
+ = `git rev-parse --verify verify--import-marks:copy-of-file2`
+'
test_expect_success 'A: export marks with large values' '
+ test_tick &&
+ mt=$(git hash-object --stdin < /dev/null) &&
+ >input.blob &&
+ >marks.exp &&
+ >tree.exp &&
+
+ cat >input.commit <<-EOF &&
+ commit refs/heads/verify--dump-marks
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ test the sparse array dumping routines with exponentially growing marks
+ COMMIT
+ EOF
+
+ i=0 l=4 m=6 n=7 &&
+ while test "$i" -lt 27
+ do
+ cat >>input.blob <<-EOF &&
+ blob
+ mark :$l
+ data 0
+ blob
+ mark :$m
+ data 0
+ blob
+ mark :$n
+ data 0
+ EOF
+ echo "M 100644 :$l l$i" >>input.commit &&
+ echo "M 100644 :$m m$i" >>input.commit &&
+ echo "M 100644 :$n n$i" >>input.commit &&
+
+ echo ":$l $mt" >>marks.exp &&
+ echo ":$m $mt" >>marks.exp &&
+ echo ":$n $mt" >>marks.exp &&
+
+ printf "100644 blob $mt\tl$i\n" >>tree.exp &&
+ printf "100644 blob $mt\tm$i\n" >>tree.exp &&
+ printf "100644 blob $mt\tn$i\n" >>tree.exp &&
+
+ l=$(($l + $l)) &&
+ m=$(($m + $m)) &&
+ n=$(($l + $n)) &&
+
+ i=$((1 + $i)) || return 1
+ done &&
+
+ sort tree.exp > tree.exp_s &&
+
cat input.blob input.commit | git fast-import --export-marks=marks.large &&
git ls-tree refs/heads/verify--dump-marks >tree.out &&
test_cmp tree.exp_s tree.out &&
- test_cmp marks.exp marks.large'
+ test_cmp marks.exp marks.large
+'
###
### series B
###
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/branch
-mark :1
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-corrupt
-COMMIT
+test_expect_success 'B: fail on invalid blob sha1' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/branch
+ mark :1
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ corrupt
+ COMMIT
+
+ from refs/heads/master
+ M 755 0000000000000000000000000000000000000001 zero1
-from refs/heads/master
-M 755 0000000000000000000000000000000000000001 zero1
+ INPUT_END
+
+ test_when_finished "rm -f .git/objects/pack_* .git/objects/index_*" &&
+ test_must_fail git fast-import <input
+'
+
+test_expect_success 'B: accept branch name "TEMP_TAG"' '
+ cat >input <<-INPUT_END &&
+ commit TEMP_TAG
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ tag base
+ COMMIT
+
+ from refs/heads/master
+
+ INPUT_END
+
+ test_when_finished "rm -f .git/TEMP_TAG
+ git gc
+ git prune" &&
+ git fast-import <input &&
+ test -f .git/TEMP_TAG &&
+ test `git rev-parse master` = `git rev-parse TEMP_TAG^`
+'
-INPUT_END
-test_expect_success 'B: fail on invalid blob sha1' '
- test_must_fail git fast-import <input
-'
-rm -f .git/objects/pack_* .git/objects/index_*
-
-cat >input <<INPUT_END
-commit TEMP_TAG
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-tag base
-COMMIT
-
-from refs/heads/master
-
-INPUT_END
-test_expect_success \
- 'B: accept branch name "TEMP_TAG"' \
- 'git fast-import <input &&
- test -f .git/TEMP_TAG &&
- test `git rev-parse master` = `git rev-parse TEMP_TAG^`'
-rm -f .git/TEMP_TAG
-
-git gc 2>/dev/null >/dev/null
-git prune 2>/dev/null >/dev/null
-
-cat >input <<INPUT_END
-commit refs/heads/empty-committer-1
-committer <> $GIT_COMMITTER_DATE
-data <<COMMIT
-empty commit
-COMMIT
-INPUT_END
test_expect_success 'B: accept empty committer' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/empty-committer-1
+ committer <> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ empty commit
+ COMMIT
+ INPUT_END
+
+ test_when_finished "git update-ref -d refs/heads/empty-committer-1
+ git gc
+ git prune" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
test -z "$out"
'
-git update-ref -d refs/heads/empty-committer-1 || true
-git gc 2>/dev/null >/dev/null
-git prune 2>/dev/null >/dev/null
-
-cat >input <<INPUT_END
-commit refs/heads/empty-committer-2
-committer <a@b.com> $GIT_COMMITTER_DATE
-data <<COMMIT
-empty commit
-COMMIT
-INPUT_END
test_expect_success 'B: accept and fixup committer with no name' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/empty-committer-2
+ committer <a@b.com> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ empty commit
+ COMMIT
+ INPUT_END
+
+ test_when_finished "git update-ref -d refs/heads/empty-committer-2
+ git gc
+ git prune" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
test -z "$out"
'
-git update-ref -d refs/heads/empty-committer-2 || true
-git gc 2>/dev/null >/dev/null
-git prune 2>/dev/null >/dev/null
-
-cat >input <<INPUT_END
-commit refs/heads/invalid-committer
-committer Name email> $GIT_COMMITTER_DATE
-data <<COMMIT
-empty commit
-COMMIT
-INPUT_END
test_expect_success 'B: fail on invalid committer (1)' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/invalid-committer
+ committer Name email> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ empty commit
+ COMMIT
+ INPUT_END
+
+ test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
test_must_fail git fast-import <input
'
-git update-ref -d refs/heads/invalid-committer || true
-cat >input <<INPUT_END
-commit refs/heads/invalid-committer
-committer Name <e<mail> $GIT_COMMITTER_DATE
-data <<COMMIT
-empty commit
-COMMIT
-INPUT_END
test_expect_success 'B: fail on invalid committer (2)' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/invalid-committer
+ committer Name <e<mail> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ empty commit
+ COMMIT
+ INPUT_END
+
+ test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
test_must_fail git fast-import <input
'
-git update-ref -d refs/heads/invalid-committer || true
-cat >input <<INPUT_END
-commit refs/heads/invalid-committer
-committer Name <email>> $GIT_COMMITTER_DATE
-data <<COMMIT
-empty commit
-COMMIT
-INPUT_END
test_expect_success 'B: fail on invalid committer (3)' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/invalid-committer
+ committer Name <email>> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ empty commit
+ COMMIT
+ INPUT_END
+
+ test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
test_must_fail git fast-import <input
'
-git update-ref -d refs/heads/invalid-committer || true
-cat >input <<INPUT_END
-commit refs/heads/invalid-committer
-committer Name <email $GIT_COMMITTER_DATE
-data <<COMMIT
-empty commit
-COMMIT
-INPUT_END
test_expect_success 'B: fail on invalid committer (4)' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/invalid-committer
+ committer Name <email $GIT_COMMITTER_DATE
+ data <<COMMIT
+ empty commit
+ COMMIT
+ INPUT_END
+
+ test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
test_must_fail git fast-import <input
'
-git update-ref -d refs/heads/invalid-committer || true
-cat >input <<INPUT_END
-commit refs/heads/invalid-committer
-committer Name<email> $GIT_COMMITTER_DATE
-data <<COMMIT
-empty commit
-COMMIT
-INPUT_END
test_expect_success 'B: fail on invalid committer (5)' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/invalid-committer
+ committer Name<email> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ empty commit
+ COMMIT
+ INPUT_END
+
+ test_when_finished "git update-ref -d refs/heads/invalid-committer" &&
test_must_fail git fast-import <input
'
-git update-ref -d refs/heads/invalid-committer || true
###
### series C
###
-newf=`echo hi newf | git hash-object -w --stdin`
-oldf=`git rev-parse --verify master:file2`
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/branch
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-second
-COMMIT
-
-from refs/heads/master
-M 644 $oldf file2/oldf
-M 755 $newf file2/newf
-D file3
-
-INPUT_END
-test_expect_success \
- 'C: incremental import create pack from stdin' \
- 'git fast-import <input &&
- git whatchanged branch'
+test_expect_success 'C: incremental import create pack from stdin' '
+ newf=`echo hi newf | git hash-object -w --stdin` &&
+ oldf=`git rev-parse --verify master:file2` &&
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/branch
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ second
+ COMMIT
+
+ from refs/heads/master
+ M 644 $oldf file2/oldf
+ M 755 $newf file2/newf
+ D file3
+
+ INPUT_END
+
+ git fast-import <input &&
+ git whatchanged branch
+'
test_expect_success 'C: verify pack' '
verify_packs
'
-test_expect_success \
- 'C: validate reuse existing blob' \
- 'test $newf = `git rev-parse --verify branch:file2/newf` &&
- test $oldf = `git rev-parse --verify branch:file2/oldf`'
-
-cat >expect <<EOF
-parent `git rev-parse --verify master^0`
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-second
-EOF
-test_expect_success \
- 'C: verify commit' \
- 'git cat-file commit branch | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect <<EOF
-:000000 100755 0000000000000000000000000000000000000000 f1fb5da718392694d0076d677d6d0e364c79b0bc A file2/newf
-:100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100 file2 file2/oldf
-:100644 000000 0d92e9f3374ae2947c23aa477cbc68ce598135f1 0000000000000000000000000000000000000000 D file3
-EOF
-git diff-tree -M -r master branch >actual
-test_expect_success \
- 'C: validate rename result' \
- 'compare_diff_raw expect actual'
+test_expect_success 'C: validate reuse existing blob' '
+ test $newf = `git rev-parse --verify branch:file2/newf` &&
+ test $oldf = `git rev-parse --verify branch:file2/oldf`
+'
+
+test_expect_success 'C: verify commit' '
+ cat >expect <<-EOF &&
+ parent `git rev-parse --verify master^0`
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+ second
+ EOF
+
+ git cat-file commit branch | sed 1d >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'C: validate rename result' '
+ cat >expect <<-EOF &&
+ :000000 100755 0000000000000000000000000000000000000000 f1fb5da718392694d0076d677d6d0e364c79b0bc A file2/newf
+ :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100 file2 file2/oldf
+ :100644 000000 0d92e9f3374ae2947c23aa477cbc68ce598135f1 0000000000000000000000000000000000000000 D file3
+ EOF
+ git diff-tree -M -r master branch >actual &&
+ compare_diff_raw expect actual
+'
###
### series D
###
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/branch
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-third
-COMMIT
-
-from refs/heads/branch^0
-M 644 inline newdir/interesting
-data <<EOF
-$file5_data
-EOF
-
-M 755 inline newdir/exec.sh
-data <<EOF
-$file6_data
-EOF
-
-INPUT_END
-test_expect_success \
- 'D: inline data in commit' \
- 'git fast-import <input &&
- git whatchanged branch'
+test_expect_success 'D: inline data in commit' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/branch
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ third
+ COMMIT
+
+ from refs/heads/branch^0
+ M 644 inline newdir/interesting
+ data <<EOF
+ $file5_data
+ EOF
+
+ M 755 inline newdir/exec.sh
+ data <<EOF
+ $file6_data
+ EOF
+
+ INPUT_END
+
+ git fast-import <input &&
+ git whatchanged branch
+'
test_expect_success 'D: verify pack' '
verify_packs
'
-cat >expect <<EOF
-:000000 100755 0000000000000000000000000000000000000000 e74b7d465e52746be2b4bae983670711e6e66657 A newdir/exec.sh
-:000000 100644 0000000000000000000000000000000000000000 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 A newdir/interesting
-EOF
-git diff-tree -M -r branch^ branch >actual
-test_expect_success \
- 'D: validate new files added' \
- 'compare_diff_raw expect actual'
+test_expect_success 'D: validate new files added' '
+ cat >expect <<-EOF &&
+ :000000 100755 0000000000000000000000000000000000000000 e74b7d465e52746be2b4bae983670711e6e66657 A newdir/exec.sh
+ :000000 100644 0000000000000000000000000000000000000000 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 A newdir/interesting
+ EOF
+ git diff-tree -M -r branch^ branch >actual &&
+ compare_diff_raw expect actual
+'
-echo "$file5_data" >expect
-test_expect_success \
- 'D: verify file5' \
- 'git cat-file blob branch:newdir/interesting >actual &&
- test_cmp expect actual'
+test_expect_success 'D: verify file5' '
+ echo "$file5_data" >expect &&
+ git cat-file blob branch:newdir/interesting >actual &&
+ test_cmp expect actual
+'
-echo "$file6_data" >expect
-test_expect_success \
- 'D: verify file6' \
- 'git cat-file blob branch:newdir/exec.sh >actual &&
- test_cmp expect actual'
+test_expect_success 'D: verify file6' '
+ echo "$file6_data" >expect &&
+ git cat-file blob branch:newdir/exec.sh >actual &&
+ test_cmp expect actual
+'
###
### series E
###
-cat >input <<INPUT_END
-commit refs/heads/branch
-author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> Tue Feb 6 11:22:18 2007 -0500
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> Tue Feb 6 12:35:02 2007 -0500
-data <<COMMIT
-RFC 2822 type date
-COMMIT
+test_expect_success 'E: rfc2822 date, --date-format=raw' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/branch
+ author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> Tue Feb 6 11:22:18 2007 -0500
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> Tue Feb 6 12:35:02 2007 -0500
+ data <<COMMIT
+ RFC 2822 type date
+ COMMIT
+
+ from refs/heads/branch^0
-from refs/heads/branch^0
+ INPUT_END
-INPUT_END
-test_expect_success 'E: rfc2822 date, --date-format=raw' '
- test_must_fail git fast-import --date-format=raw <input
+ test_must_fail git fast-import --date-format=raw <input
+'
+test_expect_success 'E: rfc2822 date, --date-format=rfc2822' '
+ git fast-import --date-format=rfc2822 <input
'
-test_expect_success \
- 'E: rfc2822 date, --date-format=rfc2822' \
- 'git fast-import --date-format=rfc2822 <input'
test_expect_success 'E: verify pack' '
verify_packs
'
-cat >expect <<EOF
-author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 1170778938 -0500
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1170783302 -0500
+test_expect_success 'E: verify commit' '
+ cat >expect <<-EOF &&
+ author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 1170778938 -0500
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1170783302 -0500
-RFC 2822 type date
-EOF
-test_expect_success \
- 'E: verify commit' \
- 'git cat-file commit branch | sed 1,2d >actual &&
- test_cmp expect actual'
+ RFC 2822 type date
+ EOF
+ git cat-file commit branch | sed 1,2d >actual &&
+ test_cmp expect actual
+'
###
### series F
###
-old_branch=`git rev-parse --verify branch^0`
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/branch
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-losing things already?
-COMMIT
-
-from refs/heads/branch~1
-
-reset refs/heads/other
-from refs/heads/branch
-
-INPUT_END
-test_expect_success \
- 'F: non-fast-forward update skips' \
- 'if git fast-import <input
- then
- echo BAD gfi did not fail
- return 1
- else
- if test $old_branch = `git rev-parse --verify branch^0`
- then
- : branch unaffected and failure returned
- return 0
- else
- echo BAD gfi changed branch $old_branch
- return 1
- fi
- fi
- '
+test_expect_success 'F: non-fast-forward update skips' '
+ old_branch=`git rev-parse --verify branch^0` &&
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/branch
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ losing things already?
+ COMMIT
+
+ from refs/heads/branch~1
+
+ reset refs/heads/other
+ from refs/heads/branch
+
+ INPUT_END
+
+ test_must_fail git fast-import <input &&
+ # branch must remain unaffected
+ test $old_branch = `git rev-parse --verify branch^0`
+'
test_expect_success 'F: verify pack' '
verify_packs
'
-cat >expect <<EOF
-tree `git rev-parse branch~1^{tree}`
-parent `git rev-parse branch~1`
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+test_expect_success 'F: verify other commit' '
+ cat >expect <<-EOF &&
+ tree `git rev-parse branch~1^{tree}`
+ parent `git rev-parse branch~1`
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-losing things already?
-EOF
-test_expect_success \
- 'F: verify other commit' \
- 'git cat-file commit other >actual &&
- test_cmp expect actual'
+ losing things already?
+ EOF
+ git cat-file commit other >actual &&
+ test_cmp expect actual
+'
###
### series G
###
-old_branch=`git rev-parse --verify branch^0`
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/branch
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-losing things already?
-COMMIT
+test_expect_success 'G: non-fast-forward update forced' '
+ old_branch=`git rev-parse --verify branch^0` &&
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/branch
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ losing things already?
+ COMMIT
-from refs/heads/branch~1
+ from refs/heads/branch~1
-INPUT_END
-test_expect_success \
- 'G: non-fast-forward update forced' \
- 'git fast-import --force <input'
+ INPUT_END
+ git fast-import --force <input
+'
test_expect_success 'G: verify pack' '
verify_packs
'
-test_expect_success \
- 'G: branch changed, but logged' \
- 'test $old_branch != `git rev-parse --verify branch^0` &&
- test $old_branch = `git rev-parse --verify branch@{1}`'
+test_expect_success 'G: branch changed, but logged' '
+ test $old_branch != `git rev-parse --verify branch^0` &&
+ test $old_branch = `git rev-parse --verify branch@{1}`
+'
###
### series H
###
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/H
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-third
-COMMIT
-
-from refs/heads/branch^0
-M 644 inline i-will-die
-data <<EOF
-this file will never exist.
-EOF
-
-deleteall
-M 644 inline h/e/l/lo
-data <<EOF
-$file5_data
-EOF
-
-INPUT_END
-test_expect_success \
- 'H: deletall, add 1' \
- 'git fast-import <input &&
- git whatchanged H'
+test_expect_success 'H: deletall, add 1' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/H
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ third
+ COMMIT
+
+ from refs/heads/branch^0
+ M 644 inline i-will-die
+ data <<EOF
+ this file will never exist.
+ EOF
+
+ deleteall
+ M 644 inline h/e/l/lo
+ data <<EOF
+ $file5_data
+ EOF
+
+ INPUT_END
+ git fast-import <input &&
+ git whatchanged H
+'
test_expect_success 'H: verify pack' '
verify_packs
'
-cat >expect <<EOF
-:100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file2/newf
-:100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D file2/oldf
-:100755 000000 85df50785d62d3b05ab03d9cbf7e4a0b49449730 0000000000000000000000000000000000000000 D file4
-:100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100 newdir/interesting h/e/l/lo
-:100755 000000 e74b7d465e52746be2b4bae983670711e6e66657 0000000000000000000000000000000000000000 D newdir/exec.sh
-EOF
-git diff-tree -M -r H^ H >actual
-test_expect_success \
- 'H: validate old files removed, new files added' \
- 'compare_diff_raw expect actual'
-
-echo "$file5_data" >expect
-test_expect_success \
- 'H: verify file' \
- 'git cat-file blob H:h/e/l/lo >actual &&
- test_cmp expect actual'
+test_expect_success 'H: validate old files removed, new files added' '
+ cat >expect <<-EOF &&
+ :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file2/newf
+ :100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D file2/oldf
+ :100755 000000 85df50785d62d3b05ab03d9cbf7e4a0b49449730 0000000000000000000000000000000000000000 D file4
+ :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100 newdir/interesting h/e/l/lo
+ :100755 000000 e74b7d465e52746be2b4bae983670711e6e66657 0000000000000000000000000000000000000000 D newdir/exec.sh
+ EOF
+ git diff-tree -M -r H^ H >actual &&
+ compare_diff_raw expect actual
+'
+
+test_expect_success 'H: verify file' '
+ echo "$file5_data" >expect &&
+ git cat-file blob H:h/e/l/lo >actual &&
+ test_cmp expect actual
+'
###
### series I
###
-cat >input <<INPUT_END
-commit refs/heads/export-boundary
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-we have a border. its only 40 characters wide.
-COMMIT
+test_expect_success 'I: export-pack-edges' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/export-boundary
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ we have a border. its only 40 characters wide.
+ COMMIT
-from refs/heads/branch
+ from refs/heads/branch
-INPUT_END
-test_expect_success \
- 'I: export-pack-edges' \
- 'git fast-import --export-pack-edges=edges.list <input'
+ INPUT_END
+ git fast-import --export-pack-edges=edges.list <input
+'
-cat >expect <<EOF
-.git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary`
-EOF
-test_expect_success \
- 'I: verify edge list' \
- 'sed -e s/pack-.*pack/pack-.pack/ edges.list >actual &&
- test_cmp expect actual'
+test_expect_success 'I: verify edge list' '
+ cat >expect <<-EOF &&
+ .git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary`
+ EOF
+ sed -e s/pack-.*pack/pack-.pack/ edges.list >actual &&
+ test_cmp expect actual
+'
###
### series J
###
-cat >input <<INPUT_END
-commit refs/heads/J
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-create J
-COMMIT
-
-from refs/heads/branch
-
-reset refs/heads/J
-
-commit refs/heads/J
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-initialize J
-COMMIT
-
-INPUT_END
-test_expect_success \
- 'J: reset existing branch creates empty commit' \
- 'git fast-import <input'
-test_expect_success \
- 'J: branch has 1 commit, empty tree' \
- 'test 1 = `git rev-list J | wc -l` &&
- test 0 = `git ls-tree J | wc -l`'
-
-cat >input <<INPUT_END
-reset refs/heads/J2
-
-tag wrong_tag
-from refs/heads/J2
-data <<EOF
-Tag branch that was reset.
-EOF
-INPUT_END
-test_expect_success \
- 'J: tag must fail on empty branch' \
- 'test_must_fail git fast-import <input'
+test_expect_success 'J: reset existing branch creates empty commit' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/J
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ create J
+ COMMIT
+
+ from refs/heads/branch
+
+ reset refs/heads/J
+
+ commit refs/heads/J
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ initialize J
+ COMMIT
+
+ INPUT_END
+ git fast-import <input
+'
+test_expect_success 'J: branch has 1 commit, empty tree' '
+ test 1 = `git rev-list J | wc -l` &&
+ test 0 = `git ls-tree J | wc -l`
+'
+
+test_expect_success 'J: tag must fail on empty branch' '
+ cat >input <<-INPUT_END &&
+ reset refs/heads/J2
+
+ tag wrong_tag
+ from refs/heads/J2
+ data <<EOF
+ Tag branch that was reset.
+ EOF
+ INPUT_END
+ test_must_fail git fast-import <input
+'
+
###
### series K
###
-cat >input <<INPUT_END
-commit refs/heads/K
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-create K
-COMMIT
+test_expect_success 'K: reinit branch with from' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/K
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ create K
+ COMMIT
-from refs/heads/branch
+ from refs/heads/branch
-commit refs/heads/K
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-redo K
-COMMIT
+ commit refs/heads/K
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ redo K
+ COMMIT
-from refs/heads/branch^1
+ from refs/heads/branch^1
-INPUT_END
-test_expect_success \
- 'K: reinit branch with from' \
- 'git fast-import <input'
-test_expect_success \
- 'K: verify K^1 = branch^1' \
- 'test `git rev-parse --verify branch^1` \
- = `git rev-parse --verify K^1`'
+ INPUT_END
+ git fast-import <input
+'
+test_expect_success 'K: verify K^1 = branch^1' '
+ test `git rev-parse --verify branch^1` \
+ = `git rev-parse --verify K^1`
+'
###
### series L
###
-cat >input <<INPUT_END
-blob
-mark :1
-data <<EOF
-some data
-EOF
-
-blob
-mark :2
-data <<EOF
-other data
-EOF
-
-commit refs/heads/L
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-create L
-COMMIT
-
-M 644 :1 b.
-M 644 :1 b/other
-M 644 :1 ba
-
-commit refs/heads/L
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-update L
-COMMIT
-
-M 644 :2 b.
-M 644 :2 b/other
-M 644 :2 ba
-INPUT_END
-
-cat >expect <<EXPECT_END
-:100644 100644 4268632... 55d3a52... M b.
-:040000 040000 0ae5cac... 443c768... M b
-:100644 100644 4268632... 55d3a52... M ba
-EXPECT_END
-
-test_expect_success \
- 'L: verify internal tree sorting' \
- 'git fast-import <input &&
- git diff-tree --abbrev --raw L^ L >output &&
- test_cmp expect output'
-
-cat >input <<INPUT_END
-blob
-mark :1
-data <<EOF
-the data
-EOF
-
-commit refs/heads/L2
-committer C O Mitter <committer@example.com> 1112912473 -0700
-data <<COMMIT
-init L2
-COMMIT
-M 644 :1 a/b/c
-M 644 :1 a/b/d
-M 644 :1 a/e/f
-
-commit refs/heads/L2
-committer C O Mitter <committer@example.com> 1112912473 -0700
-data <<COMMIT
-update L2
-COMMIT
-C a g
-C a/e g/b
-M 644 :1 g/b/h
-INPUT_END
-
-cat <<EOF >expect
-g/b/f
-g/b/h
-EOF
-
-test_expect_success \
- 'L: nested tree copy does not corrupt deltas' \
- 'git fast-import <input &&
+test_expect_success 'L: verify internal tree sorting' '
+ cat >input <<-INPUT_END &&
+ blob
+ mark :1
+ data <<EOF
+ some data
+ EOF
+
+ blob
+ mark :2
+ data <<EOF
+ other data
+ EOF
+
+ commit refs/heads/L
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ create L
+ COMMIT
+
+ M 644 :1 b.
+ M 644 :1 b/other
+ M 644 :1 ba
+
+ commit refs/heads/L
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ update L
+ COMMIT
+
+ M 644 :2 b.
+ M 644 :2 b/other
+ M 644 :2 ba
+ INPUT_END
+
+ cat >expect <<-EXPECT_END &&
+ :100644 100644 4268632... 55d3a52... M b.
+ :040000 040000 0ae5cac... 443c768... M b
+ :100644 100644 4268632... 55d3a52... M ba
+ EXPECT_END
+
+ git fast-import <input &&
+ git diff-tree --abbrev --raw L^ L >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'L: nested tree copy does not corrupt deltas' '
+ cat >input <<-INPUT_END &&
+ blob
+ mark :1
+ data <<EOF
+ the data
+ EOF
+
+ commit refs/heads/L2
+ committer C O Mitter <committer@example.com> 1112912473 -0700
+ data <<COMMIT
+ init L2
+ COMMIT
+ M 644 :1 a/b/c
+ M 644 :1 a/b/d
+ M 644 :1 a/e/f
+
+ commit refs/heads/L2
+ committer C O Mitter <committer@example.com> 1112912473 -0700
+ data <<COMMIT
+ update L2
+ COMMIT
+ C a g
+ C a/e g/b
+ M 644 :1 g/b/h
+ INPUT_END
+
+ cat >expect <<-\EOF &&
+ g/b/f
+ g/b/h
+ EOF
+
+ test_when_finished "git update-ref -d refs/heads/L2" &&
+ git fast-import <input &&
git ls-tree L2 g/b/ >tmp &&
cat tmp | cut -f 2 >actual &&
test_cmp expect actual &&
- git fsck `git rev-parse L2`'
-
-git update-ref -d refs/heads/L2
+ git fsck `git rev-parse L2`
+'
###
### series M
###
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/M1
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-file rename
-COMMIT
-
-from refs/heads/branch^0
-R file2/newf file2/n.e.w.f
-
-INPUT_END
-
-cat >expect <<EOF
-:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 file2/newf file2/n.e.w.f
-EOF
-test_expect_success \
- 'M: rename file in same subdirectory' \
- 'git fast-import <input &&
- git diff-tree -M -r M1^ M1 >actual &&
- compare_diff_raw expect actual'
-
-cat >input <<INPUT_END
-commit refs/heads/M2
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-file rename
-COMMIT
-
-from refs/heads/branch^0
-R file2/newf i/am/new/to/you
-
-INPUT_END
-
-cat >expect <<EOF
-:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 file2/newf i/am/new/to/you
-EOF
-test_expect_success \
- 'M: rename file to new subdirectory' \
- 'git fast-import <input &&
- git diff-tree -M -r M2^ M2 >actual &&
- compare_diff_raw expect actual'
-
-cat >input <<INPUT_END
-commit refs/heads/M3
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-file rename
-COMMIT
-
-from refs/heads/M2^0
-R i other/sub
-
-INPUT_END
-
-cat >expect <<EOF
-:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 i/am/new/to/you other/sub/am/new/to/you
-EOF
-test_expect_success \
- 'M: rename subdirectory to new subdirectory' \
- 'git fast-import <input &&
- git diff-tree -M -r M3^ M3 >actual &&
- compare_diff_raw expect actual'
-
-cat >input <<INPUT_END
-commit refs/heads/M4
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-rename root
-COMMIT
-
-from refs/heads/M2^0
-R "" sub
-
-INPUT_END
-
-cat >expect <<EOF
-:100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100 file2/oldf sub/file2/oldf
-:100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 R100 file4 sub/file4
-:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 i/am/new/to/you sub/i/am/new/to/you
-:100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 R100 newdir/exec.sh sub/newdir/exec.sh
-:100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100 newdir/interesting sub/newdir/interesting
-EOF
-test_expect_success \
- 'M: rename root to subdirectory' \
- 'git fast-import <input &&
- git diff-tree -M -r M4^ M4 >actual &&
- cat actual &&
- compare_diff_raw expect actual'
+test_expect_success 'M: rename file in same subdirectory' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/M1
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ file rename
+ COMMIT
+
+ from refs/heads/branch^0
+ R file2/newf file2/n.e.w.f
+
+ INPUT_END
+
+ cat >expect <<-EOF &&
+ :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 file2/newf file2/n.e.w.f
+ EOF
+ git fast-import <input &&
+ git diff-tree -M -r M1^ M1 >actual &&
+ compare_diff_raw expect actual
+'
+
+test_expect_success 'M: rename file to new subdirectory' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/M2
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ file rename
+ COMMIT
+
+ from refs/heads/branch^0
+ R file2/newf i/am/new/to/you
+
+ INPUT_END
+
+ cat >expect <<-EOF &&
+ :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 file2/newf i/am/new/to/you
+ EOF
+ git fast-import <input &&
+ git diff-tree -M -r M2^ M2 >actual &&
+ compare_diff_raw expect actual
+'
+
+test_expect_success 'M: rename subdirectory to new subdirectory' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/M3
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ file rename
+ COMMIT
+
+ from refs/heads/M2^0
+ R i other/sub
+
+ INPUT_END
+
+ cat >expect <<-EOF &&
+ :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 i/am/new/to/you other/sub/am/new/to/you
+ EOF
+ git fast-import <input &&
+ git diff-tree -M -r M3^ M3 >actual &&
+ compare_diff_raw expect actual
+'
+
+test_expect_success 'M: rename root to subdirectory' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/M4
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ rename root
+ COMMIT
+
+ from refs/heads/M2^0
+ R "" sub
+
+ INPUT_END
+
+ cat >expect <<-EOF &&
+ :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100 file2/oldf sub/file2/oldf
+ :100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 R100 file4 sub/file4
+ :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 i/am/new/to/you sub/i/am/new/to/you
+ :100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 R100 newdir/exec.sh sub/newdir/exec.sh
+ :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100 newdir/interesting sub/newdir/interesting
+ EOF
+ git fast-import <input &&
+ git diff-tree -M -r M4^ M4 >actual &&
+ cat actual &&
+ compare_diff_raw expect actual
+'
###
### series N
###
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/N1
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-file copy
-COMMIT
-
-from refs/heads/branch^0
-C file2/newf file2/n.e.w.f
-
-INPUT_END
-
-cat >expect <<EOF
-:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file2/n.e.w.f
-EOF
-test_expect_success \
- 'N: copy file in same subdirectory' \
- 'git fast-import <input &&
- git diff-tree -C --find-copies-harder -r N1^ N1 >actual &&
- compare_diff_raw expect actual'
-
-cat >input <<INPUT_END
-commit refs/heads/N2
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-clean directory copy
-COMMIT
-
-from refs/heads/branch^0
-C file2 file3
-
-commit refs/heads/N2
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-modify directory copy
-COMMIT
-
-M 644 inline file3/file5
-data <<EOF
-$file5_data
-EOF
-
-INPUT_END
-
-cat >expect <<EOF
-:100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100 newdir/interesting file3/file5
-:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf
-:100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf
-EOF
-test_expect_success \
- 'N: copy then modify subdirectory' \
- 'git fast-import <input &&
- git diff-tree -C --find-copies-harder -r N2^^ N2 >actual &&
- compare_diff_raw expect actual'
-
-cat >input <<INPUT_END
-commit refs/heads/N3
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-dirty directory copy
-COMMIT
-
-from refs/heads/branch^0
-M 644 inline file2/file5
-data <<EOF
-$file5_data
-EOF
-
-C file2 file3
-D file2/file5
-
-INPUT_END
-
-test_expect_success \
- 'N: copy dirty subdirectory' \
- 'git fast-import <input &&
- test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`'
-
-test_expect_success \
- 'N: copy directory by id' \
- 'cat >expect <<-\EOF &&
+test_expect_success 'N: copy file in same subdirectory' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/N1
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ file copy
+ COMMIT
+
+ from refs/heads/branch^0
+ C file2/newf file2/n.e.w.f
+
+ INPUT_END
+
+ cat >expect <<-EOF &&
+ :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file2/n.e.w.f
+ EOF
+ git fast-import <input &&
+ git diff-tree -C --find-copies-harder -r N1^ N1 >actual &&
+ compare_diff_raw expect actual
+'
+
+test_expect_success 'N: copy then modify subdirectory' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/N2
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ clean directory copy
+ COMMIT
+
+ from refs/heads/branch^0
+ C file2 file3
+
+ commit refs/heads/N2
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ modify directory copy
+ COMMIT
+
+ M 644 inline file3/file5
+ data <<EOF
+ $file5_data
+ EOF
+
+ INPUT_END
+
+ cat >expect <<-EOF &&
+ :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100 newdir/interesting file3/file5
+ :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf
+ :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf
+ EOF
+ git fast-import <input &&
+ git diff-tree -C --find-copies-harder -r N2^^ N2 >actual &&
+ compare_diff_raw expect actual
+'
+
+test_expect_success 'N: copy dirty subdirectory' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/N3
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ dirty directory copy
+ COMMIT
+
+ from refs/heads/branch^0
+ M 644 inline file2/file5
+ data <<EOF
+ $file5_data
+ EOF
+
+ C file2 file3
+ D file2/file5
+
+ INPUT_END
+
+ git fast-import <input &&
+ test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`
+'
+
+test_expect_success 'N: copy directory by id' '
+ cat >expect <<-\EOF &&
:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf
:100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf
EOF
- subdir=$(git rev-parse refs/heads/branch^0:file2) &&
- cat >input <<-INPUT_END &&
+ subdir=$(git rev-parse refs/heads/branch^0:file2) &&
+ cat >input <<-INPUT_END &&
commit refs/heads/N4
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
from refs/heads/branch^0
M 040000 $subdir file3
INPUT_END
- git fast-import <input &&
- git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
- compare_diff_raw expect actual'
+ git fast-import <input &&
+ git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
+ compare_diff_raw expect actual
+'
test_expect_success PIPE 'N: read and copy directory' '
cat >expect <<-\EOF &&
test_cmp expect actual
'
-test_expect_success \
- 'N: copy root directory by tree hash' \
- 'cat >expect <<-\EOF &&
+test_expect_success 'N: copy root directory by tree hash' '
+ cat >expect <<-\EOF &&
:100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file3/newf
:100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D file3/oldf
EOF
- root=$(git rev-parse refs/heads/branch^0^{tree}) &&
- cat >input <<-INPUT_END &&
+ root=$(git rev-parse refs/heads/branch^0^{tree}) &&
+ cat >input <<-INPUT_END &&
commit refs/heads/N6
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
from refs/heads/branch^0
M 040000 $root ""
INPUT_END
- git fast-import <input &&
- git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
- compare_diff_raw expect actual'
+ git fast-import <input &&
+ git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
+ compare_diff_raw expect actual
+'
-test_expect_success \
- 'N: copy root by path' \
- 'cat >expect <<-\EOF &&
+test_expect_success 'N: copy root by path' '
+ cat >expect <<-\EOF &&
:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf oldroot/file2/newf
:100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf oldroot/file2/oldf
:100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 C100 file4 oldroot/file4
:100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 C100 newdir/exec.sh oldroot/newdir/exec.sh
:100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100 newdir/interesting oldroot/newdir/interesting
EOF
- cat >input <<-INPUT_END &&
+ cat >input <<-INPUT_END &&
commit refs/heads/N-copy-root-path
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
from refs/heads/branch^0
C "" oldroot
INPUT_END
- git fast-import <input &&
- git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual &&
- compare_diff_raw expect actual'
+ git fast-import <input &&
+ git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual &&
+ compare_diff_raw expect actual
+'
-test_expect_success \
- 'N: delete directory by copying' \
- 'cat >expect <<-\EOF &&
+test_expect_success 'N: delete directory by copying' '
+ cat >expect <<-\EOF &&
OBJID
:100644 000000 OBJID OBJID D foo/bar/qux
OBJID
:000000 100644 OBJID OBJID A foo/bar/baz
:000000 100644 OBJID OBJID A foo/bar/qux
EOF
- empty_tree=$(git mktree </dev/null) &&
- cat >input <<-INPUT_END &&
+ empty_tree=$(git mktree </dev/null) &&
+ cat >input <<-INPUT_END &&
commit refs/heads/N-delete
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
M 040000 $empty_tree foo/bar/qux
INPUT_END
- git fast-import <input &&
- git rev-list N-delete |
+ git fast-import <input &&
+ git rev-list N-delete |
git diff-tree -r --stdin --root --always |
sed -e "s/$_x40/OBJID/g" >actual &&
- test_cmp expect actual'
+ test_cmp expect actual
+'
-test_expect_success \
- 'N: modify copied tree' \
- 'cat >expect <<-\EOF &&
+test_expect_success 'N: modify copied tree' '
+ cat >expect <<-\EOF &&
:100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100 newdir/interesting file3/file5
:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf
:100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf
EOF
- subdir=$(git rev-parse refs/heads/branch^0:file2) &&
- cat >input <<-INPUT_END &&
+ subdir=$(git rev-parse refs/heads/branch^0:file2) &&
+ cat >input <<-INPUT_END &&
commit refs/heads/N5
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
$file5_data
EOF
INPUT_END
- git fast-import <input &&
- git diff-tree -C --find-copies-harder -r N5^^ N5 >actual &&
- compare_diff_raw expect actual'
-
-test_expect_success \
- 'N: reject foo/ syntax' \
- 'subdir=$(git rev-parse refs/heads/branch^0:file2) &&
- test_must_fail git fast-import <<-INPUT_END
+ git fast-import <input &&
+ git diff-tree -C --find-copies-harder -r N5^^ N5 >actual &&
+ compare_diff_raw expect actual
+'
+
+test_expect_success 'N: reject foo/ syntax' '
+ subdir=$(git rev-parse refs/heads/branch^0:file2) &&
+ test_must_fail git fast-import <<-INPUT_END
commit refs/heads/N5B
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
from refs/heads/branch^0
M 040000 $subdir file3/
- INPUT_END'
+ INPUT_END
+'
-test_expect_success \
- 'N: reject foo/ syntax in copy source' \
- 'test_must_fail git fast-import <<-INPUT_END
+test_expect_success 'N: reject foo/ syntax in copy source' '
+ test_must_fail git fast-import <<-INPUT_END
commit refs/heads/N5C
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
from refs/heads/branch^0
C file2/ file3
- INPUT_END'
+ INPUT_END
+'
-test_expect_success \
- 'N: reject foo/ syntax in rename source' \
- 'test_must_fail git fast-import <<-INPUT_END
+test_expect_success 'N: reject foo/ syntax in rename source' '
+ test_must_fail git fast-import <<-INPUT_END
commit refs/heads/N5D
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
from refs/heads/branch^0
R file2/ file3
- INPUT_END'
+ INPUT_END
+'
-test_expect_success \
- 'N: reject foo/ syntax in ls argument' \
- 'test_must_fail git fast-import <<-INPUT_END
+test_expect_success 'N: reject foo/ syntax in ls argument' '
+ test_must_fail git fast-import <<-INPUT_END
commit refs/heads/N5E
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
from refs/heads/branch^0
ls "file2/"
- INPUT_END'
+ INPUT_END
+'
-test_expect_success \
- 'N: copy to root by id and modify' \
- 'echo "hello, world" >expect.foo &&
- echo hello >expect.bar &&
- git fast-import <<-SETUP_END &&
+test_expect_success 'N: copy to root by id and modify' '
+ echo "hello, world" >expect.foo &&
+ echo hello >expect.bar &&
+ git fast-import <<-SETUP_END &&
commit refs/heads/N7
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
EOF
SETUP_END
- tree=$(git rev-parse --verify N7:) &&
- git fast-import <<-INPUT_END &&
+ tree=$(git rev-parse --verify N7:) &&
+ git fast-import <<-INPUT_END &&
commit refs/heads/N8
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
hello, world
EOF
INPUT_END
- git show N8:foo/foo >actual.foo &&
- git show N8:foo/bar >actual.bar &&
- test_cmp expect.foo actual.foo &&
- test_cmp expect.bar actual.bar'
-
-test_expect_success \
- 'N: extract subtree' \
- 'branch=$(git rev-parse --verify refs/heads/branch^{tree}) &&
- cat >input <<-INPUT_END &&
+ git show N8:foo/foo >actual.foo &&
+ git show N8:foo/bar >actual.bar &&
+ test_cmp expect.foo actual.foo &&
+ test_cmp expect.bar actual.bar
+'
+
+test_expect_success 'N: extract subtree' '
+ branch=$(git rev-parse --verify refs/heads/branch^{tree}) &&
+ cat >input <<-INPUT_END &&
commit refs/heads/N9
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
M 040000 $branch ""
C "newdir" ""
INPUT_END
- git fast-import <input &&
- git diff --exit-code branch:newdir N9'
-
-test_expect_success \
- 'N: modify subtree, extract it, and modify again' \
- 'echo hello >expect.baz &&
- echo hello, world >expect.qux &&
- git fast-import <<-SETUP_END &&
+ git fast-import <input &&
+ git diff --exit-code branch:newdir N9
+'
+
+test_expect_success 'N: modify subtree, extract it, and modify again' '
+ echo hello >expect.baz &&
+ echo hello, world >expect.qux &&
+ git fast-import <<-SETUP_END &&
commit refs/heads/N10
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
- hello, tree
+ hello, tree
+ COMMIT
+
+ deleteall
+ M 644 inline foo/bar/baz
+ data <<EOF
+ hello
+ EOF
+ SETUP_END
+
+ tree=$(git rev-parse --verify N10:) &&
+ git fast-import <<-INPUT_END &&
+ commit refs/heads/N11
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ copy to root by id and modify
+ COMMIT
+
+ M 040000 $tree ""
+ M 100644 inline foo/bar/qux
+ data <<EOF
+ hello, world
+ EOF
+ R "foo" ""
+ C "bar/qux" "bar/quux"
+ INPUT_END
+ git show N11:bar/baz >actual.baz &&
+ git show N11:bar/qux >actual.qux &&
+ git show N11:bar/quux >actual.quux &&
+ test_cmp expect.baz actual.baz &&
+ test_cmp expect.qux actual.qux &&
+ test_cmp expect.qux actual.quux'
+
+###
+### series O
+###
+
+test_expect_success 'O: comments are all skipped' '
+ cat >input <<-INPUT_END &&
+ #we will
+ commit refs/heads/O1
+ # -- ignore all of this text
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ # $GIT_COMMITTER_NAME has inserted here for his benefit.
+ data <<COMMIT
+ dirty directory copy
+ COMMIT
+
+ # do not forget the import blank line!
+ #
+ # yes, we started from our usual base of branch^0.
+ # i like branch^0.
+ from refs/heads/branch^0
+ # and we need to reuse file2/file5 from N3 above.
+ M 644 inline file2/file5
+ # otherwise the tree will be different
+ data <<EOF
+ $file5_data
+ EOF
+
+ # do not forget to copy file2 to file3
+ C file2 file3
+ #
+ # or to delete file5 from file2.
+ D file2/file5
+ # are we done yet?
+
+ INPUT_END
+
+ git fast-import <input &&
+ test `git rev-parse N3` = `git rev-parse O1`
+'
+
+test_expect_success 'O: blank lines not necessary after data commands' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/O2
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ dirty directory copy
+ COMMIT
+ from refs/heads/branch^0
+ M 644 inline file2/file5
+ data <<EOF
+ $file5_data
+ EOF
+ C file2 file3
+ D file2/file5
+
+ INPUT_END
+
+ git fast-import <input &&
+ test `git rev-parse N3` = `git rev-parse O2`
+'
+
+test_expect_success 'O: repack before next test' '
+ git repack -a -d
+'
+
+test_expect_success 'O: blank lines not necessary after other commands' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/O3
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zstring
+ COMMIT
+ commit refs/heads/O3
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zof
+ COMMIT
+ checkpoint
+ commit refs/heads/O3
+ mark :5
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zempty
+ COMMIT
+ checkpoint
+ commit refs/heads/O3
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zcommits
+ COMMIT
+ reset refs/tags/O3-2nd
+ from :5
+ reset refs/tags/O3-3rd
+ from :5
+ INPUT_END
+
+ cat >expect <<-INPUT_END &&
+ string
+ of
+ empty
+ commits
+ INPUT_END
+
+ git fast-import <input &&
+ test 8 = `find .git/objects/pack -type f | wc -l` &&
+ test `git rev-parse refs/tags/O3-2nd` = `git rev-parse O3^` &&
+ git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'O: progress outputs as requested by input' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/O4
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zstring
+ COMMIT
+ commit refs/heads/O4
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zof
+ COMMIT
+ progress Two commits down, 2 to go!
+ commit refs/heads/O4
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zempty
+ COMMIT
+ progress Three commits down, 1 to go!
+ commit refs/heads/O4
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ zcommits
+ COMMIT
+ progress done!
+ INPUT_END
+ git fast-import <input >actual &&
+ grep "progress " <input >expect &&
+ test_cmp expect actual
+'
+
+###
+### series P (gitlinks)
+###
+
+test_expect_success 'P: superproject & submodule mix' '
+ cat >input <<-INPUT_END &&
+ blob
+ mark :1
+ data 10
+ test file
+
+ reset refs/heads/sub
+ commit refs/heads/sub
+ mark :2
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data 12
+ sub_initial
+ M 100644 :1 file
+
+ blob
+ mark :3
+ data <<DATAEND
+ [submodule "sub"]
+ path = sub
+ url = "`pwd`/sub"
+ DATAEND
+
+ commit refs/heads/subuse1
+ mark :4
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data 8
+ initial
+ from refs/heads/master
+ M 100644 :3 .gitmodules
+ M 160000 :2 sub
+
+ blob
+ mark :5
+ data 20
+ test file
+ more data
+
+ commit refs/heads/sub
+ mark :6
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data 11
+ sub_second
+ from :2
+ M 100644 :5 file
+
+ commit refs/heads/subuse1
+ mark :7
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data 7
+ second
+ from :4
+ M 160000 :6 sub
+
+ INPUT_END
+
+ git fast-import <input &&
+ git checkout subuse1 &&
+ rm -rf sub &&
+ mkdir sub &&
+ (
+ cd sub &&
+ git init &&
+ git fetch --update-head-ok .. refs/heads/sub:refs/heads/master &&
+ git checkout master
+ ) &&
+ git submodule init &&
+ git submodule update
+'
+
+test_expect_success 'P: verbatim SHA gitlinks' '
+ SUBLAST=$(git rev-parse --verify sub) &&
+ SUBPREV=$(git rev-parse --verify sub^) &&
+
+ cat >input <<-INPUT_END &&
+ blob
+ mark :1
+ data <<DATAEND
+ [submodule "sub"]
+ path = sub
+ url = "`pwd`/sub"
+ DATAEND
+
+ commit refs/heads/subuse2
+ mark :2
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data 8
+ initial
+ from refs/heads/master
+ M 100644 :1 .gitmodules
+ M 160000 $SUBPREV sub
+
+ commit refs/heads/subuse2
+ mark :3
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data 7
+ second
+ from :2
+ M 160000 $SUBLAST sub
+
+ INPUT_END
+
+ git branch -D sub &&
+ git gc &&
+ git prune &&
+ git fast-import <input &&
+ test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)
+'
+
+test_expect_success 'P: fail on inline gitlink' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/subuse3
+ mark :1
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ corrupt
+ COMMIT
+
+ from refs/heads/subuse2
+ M 160000 inline sub
+ data <<DATA
+ $SUBPREV
+ DATA
+
+ INPUT_END
+
+ test_must_fail git fast-import <input
+'
+
+test_expect_success 'P: fail on blob mark in gitlink' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ blob
+ mark :1
+ data <<DATA
+ $SUBPREV
+ DATA
+
+ commit refs/heads/subuse3
+ mark :2
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ corrupt
+ COMMIT
+
+ from refs/heads/subuse2
+ M 160000 :1 sub
+
+ INPUT_END
+
+ test_must_fail git fast-import <input
+'
+
+###
+### series Q (notes)
+###
+
+test_expect_success 'Q: commit notes' '
+ note1_data="The first note for the first commit" &&
+ note2_data="The first note for the second commit" &&
+ note3_data="The first note for the third commit" &&
+ note1b_data="The second note for the first commit" &&
+ note1c_data="The third note for the first commit" &&
+ note2b_data="The second note for the second commit" &&
+
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ blob
+ mark :2
+ data <<EOF
+ $file2_data
+ EOF
+
+ commit refs/heads/notes-test
+ mark :3
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ first (:3)
+ COMMIT
+
+ M 644 :2 file2
+
+ blob
+ mark :4
+ data $file4_len
+ $file4_data
+ commit refs/heads/notes-test
+ mark :5
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ second (:5)
+ COMMIT
+
+ M 644 :4 file4
+
+ commit refs/heads/notes-test
+ mark :6
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ third (:6)
+ COMMIT
+
+ M 644 inline file5
+ data <<EOF
+ $file5_data
+ EOF
+
+ M 755 inline file6
+ data <<EOF
+ $file6_data
+ EOF
+
+ blob
+ mark :7
+ data <<EOF
+ $note1_data
+ EOF
+
+ blob
+ mark :8
+ data <<EOF
+ $note2_data
+ EOF
+
+ commit refs/notes/foobar
+ mark :9
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ notes (:9)
+ COMMIT
+
+ N :7 :3
+ N :8 :5
+ N inline :6
+ data <<EOF
+ $note3_data
+ EOF
+
+ commit refs/notes/foobar
+ mark :10
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ notes (:10)
+ COMMIT
+
+ N inline :3
+ data <<EOF
+ $note1b_data
+ EOF
+
+ commit refs/notes/foobar2
+ mark :11
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ notes (:11)
COMMIT
- deleteall
- M 644 inline foo/bar/baz
+ N inline :3
data <<EOF
- hello
+ $note1c_data
EOF
- SETUP_END
- tree=$(git rev-parse --verify N10:) &&
- git fast-import <<-INPUT_END &&
- commit refs/heads/N11
+ commit refs/notes/foobar
+ mark :12
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
- copy to root by id and modify
+ notes (:12)
COMMIT
- M 040000 $tree ""
- M 100644 inline foo/bar/qux
+ deleteall
+ N inline :5
data <<EOF
- hello, world
+ $note2b_data
EOF
- R "foo" ""
- C "bar/qux" "bar/quux"
+
INPUT_END
- git show N11:bar/baz >actual.baz &&
- git show N11:bar/qux >actual.qux &&
- git show N11:bar/quux >actual.quux &&
- test_cmp expect.baz actual.baz &&
- test_cmp expect.qux actual.qux &&
- test_cmp expect.qux actual.quux'
-###
-### series O
-###
+ git fast-import <input &&
+ git whatchanged notes-test
+'
-cat >input <<INPUT_END
-#we will
-commit refs/heads/O1
-# -- ignore all of this text
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-# $GIT_COMMITTER_NAME has inserted here for his benefit.
-data <<COMMIT
-dirty directory copy
-COMMIT
-
-# don't forget the import blank line!
-#
-# yes, we started from our usual base of branch^0.
-# i like branch^0.
-from refs/heads/branch^0
-# and we need to reuse file2/file5 from N3 above.
-M 644 inline file2/file5
-# otherwise the tree will be different
-data <<EOF
-$file5_data
-EOF
-
-# don't forget to copy file2 to file3
-C file2 file3
-#
-# or to delete file5 from file2.
-D file2/file5
-# are we done yet?
-
-INPUT_END
-
-test_expect_success \
- 'O: comments are all skipped' \
- 'git fast-import <input &&
- test `git rev-parse N3` = `git rev-parse O1`'
-
-cat >input <<INPUT_END
-commit refs/heads/O2
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-dirty directory copy
-COMMIT
-from refs/heads/branch^0
-M 644 inline file2/file5
-data <<EOF
-$file5_data
-EOF
-C file2 file3
-D file2/file5
-
-INPUT_END
-
-test_expect_success \
- 'O: blank lines not necessary after data commands' \
- 'git fast-import <input &&
- test `git rev-parse N3` = `git rev-parse O2`'
-
-test_expect_success \
- 'O: repack before next test' \
- 'git repack -a -d'
-
-cat >input <<INPUT_END
-commit refs/heads/O3
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zstring
-COMMIT
-commit refs/heads/O3
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zof
-COMMIT
-checkpoint
-commit refs/heads/O3
-mark :5
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zempty
-COMMIT
-checkpoint
-commit refs/heads/O3
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zcommits
-COMMIT
-reset refs/tags/O3-2nd
-from :5
-reset refs/tags/O3-3rd
-from :5
-INPUT_END
-
-cat >expect <<INPUT_END
-string
-of
-empty
-commits
-INPUT_END
-test_expect_success \
- 'O: blank lines not necessary after other commands' \
- 'git fast-import <input &&
- test 8 = `find .git/objects/pack -type f | wc -l` &&
- test `git rev-parse refs/tags/O3-2nd` = `git rev-parse O3^` &&
- git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual &&
- test_cmp expect actual'
-
-cat >input <<INPUT_END
-commit refs/heads/O4
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zstring
-COMMIT
-commit refs/heads/O4
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zof
-COMMIT
-progress Two commits down, 2 to go!
-commit refs/heads/O4
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zempty
-COMMIT
-progress Three commits down, 1 to go!
-commit refs/heads/O4
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-zcommits
-COMMIT
-progress I'm done!
-INPUT_END
-test_expect_success \
- 'O: progress outputs as requested by input' \
- 'git fast-import <input >actual &&
- grep "progress " <input >expect &&
- test_cmp expect actual'
+test_expect_success 'Q: verify pack' '
+ verify_packs
+'
-###
-### series P (gitlinks)
-###
+test_expect_success 'Q: verify first commit' '
+ commit1=$(git rev-parse notes-test~2) &&
+ commit2=$(git rev-parse notes-test^) &&
+ commit3=$(git rev-parse notes-test) &&
-cat >input <<INPUT_END
-blob
-mark :1
-data 10
-test file
-
-reset refs/heads/sub
-commit refs/heads/sub
-mark :2
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data 12
-sub_initial
-M 100644 :1 file
-
-blob
-mark :3
-data <<DATAEND
-[submodule "sub"]
- path = sub
- url = "`pwd`/sub"
-DATAEND
-
-commit refs/heads/subuse1
-mark :4
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data 8
-initial
-from refs/heads/master
-M 100644 :3 .gitmodules
-M 160000 :2 sub
-
-blob
-mark :5
-data 20
-test file
-more data
-
-commit refs/heads/sub
-mark :6
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data 11
-sub_second
-from :2
-M 100644 :5 file
-
-commit refs/heads/subuse1
-mark :7
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data 7
-second
-from :4
-M 160000 :6 sub
-
-INPUT_END
-
-test_expect_success \
- 'P: superproject & submodule mix' \
- 'git fast-import <input &&
- git checkout subuse1 &&
- rm -rf sub && mkdir sub && (cd sub &&
- git init &&
- git fetch --update-head-ok .. refs/heads/sub:refs/heads/master &&
- git checkout master) &&
- git submodule init &&
- git submodule update'
-
-SUBLAST=$(git rev-parse --verify sub)
-SUBPREV=$(git rev-parse --verify sub^)
-
-cat >input <<INPUT_END
-blob
-mark :1
-data <<DATAEND
-[submodule "sub"]
- path = sub
- url = "`pwd`/sub"
-DATAEND
-
-commit refs/heads/subuse2
-mark :2
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data 8
-initial
-from refs/heads/master
-M 100644 :1 .gitmodules
-M 160000 $SUBPREV sub
-
-commit refs/heads/subuse2
-mark :3
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data 7
-second
-from :2
-M 160000 $SUBLAST sub
-
-INPUT_END
-
-test_expect_success \
- 'P: verbatim SHA gitlinks' \
- 'git branch -D sub &&
- git gc && git prune &&
- git fast-import <input &&
- test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)'
-
-test_tick
-cat >input <<INPUT_END
-commit refs/heads/subuse3
-mark :1
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-corrupt
-COMMIT
-
-from refs/heads/subuse2
-M 160000 inline sub
-data <<DATA
-$SUBPREV
-DATA
-
-INPUT_END
+ cat >expect <<-EOF &&
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-test_expect_success 'P: fail on inline gitlink' '
- test_must_fail git fast-import <input'
+ first (:3)
+ EOF
+ git cat-file commit notes-test~2 | sed 1d >actual &&
+ test_cmp expect actual
+'
-test_tick
-cat >input <<INPUT_END
-blob
-mark :1
-data <<DATA
-$SUBPREV
-DATA
+test_expect_success 'Q: verify second commit' '
+ cat >expect <<-EOF &&
+ parent $commit1
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-commit refs/heads/subuse3
-mark :2
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-corrupt
-COMMIT
+ second (:5)
+ EOF
+ git cat-file commit notes-test^ | sed 1d >actual &&
+ test_cmp expect actual
+'
-from refs/heads/subuse2
-M 160000 :1 sub
+test_expect_success 'Q: verify third commit' '
+ cat >expect <<-EOF &&
+ parent $commit2
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-INPUT_END
+ third (:6)
+ EOF
+ git cat-file commit notes-test | sed 1d >actual &&
+ test_cmp expect actual
+'
-test_expect_success 'P: fail on blob mark in gitlink' '
- test_must_fail git fast-import <input'
+test_expect_success 'Q: verify first notes commit' '
+ cat >expect <<-EOF &&
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-###
-### series Q (notes)
-###
+ notes (:9)
+ EOF
+ git cat-file commit refs/notes/foobar~2 | sed 1d >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify first notes tree' '
+ cat >expect.unsorted <<-EOF &&
+ 100644 blob $commit1
+ 100644 blob $commit2
+ 100644 blob $commit3
+ EOF
+ cat expect.unsorted | sort >expect &&
+ git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual
+'
-note1_data="The first note for the first commit"
-note2_data="The first note for the second commit"
-note3_data="The first note for the third commit"
-note1b_data="The second note for the first commit"
-note1c_data="The third note for the first commit"
-note2b_data="The second note for the second commit"
-
-test_tick
-cat >input <<INPUT_END
-blob
-mark :2
-data <<EOF
-$file2_data
-EOF
-
-commit refs/heads/notes-test
-mark :3
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-first (:3)
-COMMIT
-
-M 644 :2 file2
-
-blob
-mark :4
-data $file4_len
-$file4_data
-commit refs/heads/notes-test
-mark :5
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-second (:5)
-COMMIT
-
-M 644 :4 file4
-
-commit refs/heads/notes-test
-mark :6
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-third (:6)
-COMMIT
-
-M 644 inline file5
-data <<EOF
-$file5_data
-EOF
-
-M 755 inline file6
-data <<EOF
-$file6_data
-EOF
-
-blob
-mark :7
-data <<EOF
-$note1_data
-EOF
-
-blob
-mark :8
-data <<EOF
-$note2_data
-EOF
-
-commit refs/notes/foobar
-mark :9
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-notes (:9)
-COMMIT
-
-N :7 :3
-N :8 :5
-N inline :6
-data <<EOF
-$note3_data
-EOF
-
-commit refs/notes/foobar
-mark :10
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-notes (:10)
-COMMIT
-
-N inline :3
-data <<EOF
-$note1b_data
-EOF
-
-commit refs/notes/foobar2
-mark :11
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-notes (:11)
-COMMIT
-
-N inline :3
-data <<EOF
-$note1c_data
-EOF
-
-commit refs/notes/foobar
-mark :12
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-notes (:12)
-COMMIT
-
-deleteall
-N inline :5
-data <<EOF
-$note2b_data
-EOF
-
-INPUT_END
-
-test_expect_success \
- 'Q: commit notes' \
- 'git fast-import <input &&
- git whatchanged notes-test'
+test_expect_success 'Q: verify first note for first commit' '
+ echo "$note1_data" >expect &&
+ git cat-file blob refs/notes/foobar~2:$commit1 >actual &&
+ test_cmp expect actual
+'
-test_expect_success 'Q: verify pack' '
- verify_packs
+test_expect_success 'Q: verify first note for second commit' '
+ echo "$note2_data" >expect &&
+ git cat-file blob refs/notes/foobar~2:$commit2 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify first note for third commit' '
+ echo "$note3_data" >expect &&
+ git cat-file blob refs/notes/foobar~2:$commit3 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify second notes commit' '
+ cat >expect <<-EOF &&
+ parent `git rev-parse --verify refs/notes/foobar~2`
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+ notes (:10)
+ EOF
+ git cat-file commit refs/notes/foobar^ | sed 1d >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify second notes tree' '
+ cat >expect.unsorted <<-EOF &&
+ 100644 blob $commit1
+ 100644 blob $commit2
+ 100644 blob $commit3
+ EOF
+ cat expect.unsorted | sort >expect &&
+ git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify second note for first commit' '
+ echo "$note1b_data" >expect &&
+ git cat-file blob refs/notes/foobar^:$commit1 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify first note for second commit' '
+ echo "$note2_data" >expect &&
+ git cat-file blob refs/notes/foobar^:$commit2 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify first note for third commit' '
+ echo "$note3_data" >expect &&
+ git cat-file blob refs/notes/foobar^:$commit3 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify third notes commit' '
+ cat >expect <<-EOF &&
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+ notes (:11)
+ EOF
+ git cat-file commit refs/notes/foobar2 | sed 1d >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify third notes tree' '
+ cat >expect.unsorted <<-EOF &&
+ 100644 blob $commit1
+ EOF
+ cat expect.unsorted | sort >expect &&
+ git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual
'
-commit1=$(git rev-parse notes-test~2)
-commit2=$(git rev-parse notes-test^)
-commit3=$(git rev-parse notes-test)
-
-cat >expect <<EOF
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-first (:3)
-EOF
-test_expect_success \
- 'Q: verify first commit' \
- 'git cat-file commit notes-test~2 | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect <<EOF
-parent $commit1
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-second (:5)
-EOF
-test_expect_success \
- 'Q: verify second commit' \
- 'git cat-file commit notes-test^ | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect <<EOF
-parent $commit2
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-third (:6)
-EOF
-test_expect_success \
- 'Q: verify third commit' \
- 'git cat-file commit notes-test | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect <<EOF
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-notes (:9)
-EOF
-test_expect_success \
- 'Q: verify first notes commit' \
- 'git cat-file commit refs/notes/foobar~2 | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect.unsorted <<EOF
-100644 blob $commit1
-100644 blob $commit2
-100644 blob $commit3
-EOF
-cat expect.unsorted | sort >expect
-test_expect_success \
- 'Q: verify first notes tree' \
- 'git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
- test_cmp expect actual'
-
-echo "$note1_data" >expect
-test_expect_success \
- 'Q: verify first note for first commit' \
- 'git cat-file blob refs/notes/foobar~2:$commit1 >actual && test_cmp expect actual'
-
-echo "$note2_data" >expect
-test_expect_success \
- 'Q: verify first note for second commit' \
- 'git cat-file blob refs/notes/foobar~2:$commit2 >actual && test_cmp expect actual'
-
-echo "$note3_data" >expect
-test_expect_success \
- 'Q: verify first note for third commit' \
- 'git cat-file blob refs/notes/foobar~2:$commit3 >actual && test_cmp expect actual'
-
-cat >expect <<EOF
-parent `git rev-parse --verify refs/notes/foobar~2`
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-notes (:10)
-EOF
-test_expect_success \
- 'Q: verify second notes commit' \
- 'git cat-file commit refs/notes/foobar^ | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect.unsorted <<EOF
-100644 blob $commit1
-100644 blob $commit2
-100644 blob $commit3
-EOF
-cat expect.unsorted | sort >expect
-test_expect_success \
- 'Q: verify second notes tree' \
- 'git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
- test_cmp expect actual'
-
-echo "$note1b_data" >expect
-test_expect_success \
- 'Q: verify second note for first commit' \
- 'git cat-file blob refs/notes/foobar^:$commit1 >actual && test_cmp expect actual'
-
-echo "$note2_data" >expect
-test_expect_success \
- 'Q: verify first note for second commit' \
- 'git cat-file blob refs/notes/foobar^:$commit2 >actual && test_cmp expect actual'
-
-echo "$note3_data" >expect
-test_expect_success \
- 'Q: verify first note for third commit' \
- 'git cat-file blob refs/notes/foobar^:$commit3 >actual && test_cmp expect actual'
-
-cat >expect <<EOF
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-notes (:11)
-EOF
-test_expect_success \
- 'Q: verify third notes commit' \
- 'git cat-file commit refs/notes/foobar2 | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect.unsorted <<EOF
-100644 blob $commit1
-EOF
-cat expect.unsorted | sort >expect
-test_expect_success \
- 'Q: verify third notes tree' \
- 'git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
- test_cmp expect actual'
-
-echo "$note1c_data" >expect
-test_expect_success \
- 'Q: verify third note for first commit' \
- 'git cat-file blob refs/notes/foobar2:$commit1 >actual && test_cmp expect actual'
-
-cat >expect <<EOF
-parent `git rev-parse --verify refs/notes/foobar^`
-author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-
-notes (:12)
-EOF
-test_expect_success \
- 'Q: verify fourth notes commit' \
- 'git cat-file commit refs/notes/foobar | sed 1d >actual &&
- test_cmp expect actual'
-
-cat >expect.unsorted <<EOF
-100644 blob $commit2
-EOF
-cat expect.unsorted | sort >expect
-test_expect_success \
- 'Q: verify fourth notes tree' \
- 'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
- test_cmp expect actual'
-
-echo "$note2b_data" >expect
-test_expect_success \
- 'Q: verify second note for second commit' \
- 'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'
-
-cat >input <<EOF
-reset refs/heads/Q0
-
-commit refs/heads/note-Q0
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-Note for an empty branch.
-COMMIT
-
-N inline refs/heads/Q0
-data <<NOTE
-some note
-NOTE
-EOF
-test_expect_success \
- 'Q: deny note on empty branch' \
- 'test_must_fail git fast-import <input'
+test_expect_success 'Q: verify third note for first commit' '
+ echo "$note1c_data" >expect &&
+ git cat-file blob refs/notes/foobar2:$commit1 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify fourth notes commit' '
+ cat >expect <<-EOF &&
+ parent `git rev-parse --verify refs/notes/foobar^`
+ author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+ notes (:12)
+ EOF
+ git cat-file commit refs/notes/foobar | sed 1d >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify fourth notes tree' '
+ cat >expect.unsorted <<-EOF &&
+ 100644 blob $commit2
+ EOF
+ cat expect.unsorted | sort >expect &&
+ git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: verify second note for second commit' '
+ echo "$note2b_data" >expect &&
+ git cat-file blob refs/notes/foobar:$commit2 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Q: deny note on empty branch' '
+ cat >input <<-EOF &&
+ reset refs/heads/Q0
+
+ commit refs/heads/note-Q0
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ Note for an empty branch.
+ COMMIT
+
+ N inline refs/heads/Q0
+ data <<NOTE
+ some note
+ NOTE
+ EOF
+ test_must_fail git fast-import <input
+'
###
### series R (feature and option)
###
-cat >input <<EOF
-feature no-such-feature-exists
-EOF
-
test_expect_success 'R: abort on unsupported feature' '
+ cat >input <<-EOF &&
+ feature no-such-feature-exists
+ EOF
+
test_must_fail git fast-import <input
'
-cat >input <<EOF
-feature date-format=now
-EOF
-
test_expect_success 'R: supported feature is accepted' '
+ cat >input <<-EOF &&
+ feature date-format=now
+ EOF
+
git fast-import <input
'
-cat >input << EOF
-blob
-data 3
-hi
-feature date-format=now
-EOF
-
test_expect_success 'R: abort on receiving feature after data command' '
+ cat >input <<-EOF &&
+ blob
+ data 3
+ hi
+ feature date-format=now
+ EOF
+
test_must_fail git fast-import <input
'
-cat >input << EOF
-feature import-marks=git.marks
-feature import-marks=git2.marks
-EOF
-
test_expect_success 'R: only one import-marks feature allowed per stream' '
+ cat >input <<-EOF &&
+ feature import-marks=git.marks
+ feature import-marks=git2.marks
+ EOF
+
test_must_fail git fast-import <input
'
-cat >input << EOF
-feature export-marks=git.marks
-blob
-mark :1
-data 3
-hi
+test_expect_success 'R: export-marks feature results in a marks file being created' '
+ cat >input <<-EOF &&
+ feature export-marks=git.marks
+ blob
+ mark :1
+ data 3
+ hi
-EOF
+ EOF
-test_expect_success \
- 'R: export-marks feature results in a marks file being created' \
- 'cat input | git fast-import &&
- grep :1 git.marks'
+ cat input | git fast-import &&
+ grep :1 git.marks
+'
-test_expect_success \
- 'R: export-marks options can be overridden by commandline options' \
- 'cat input | git fast-import --export-marks=other.marks &&
- grep :1 other.marks'
+test_expect_success 'R: export-marks options can be overridden by commandline options' '
+ cat input | git fast-import --export-marks=other.marks &&
+ grep :1 other.marks
+'
test_expect_success 'R: catch typo in marks file name' '
test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null &&
test_cmp expect io.marks
'
-cat >input << EOF
-feature import-marks=marks.out
-feature export-marks=marks.new
-EOF
-
-test_expect_success \
- 'R: import to output marks works without any content' \
- 'cat input | git fast-import &&
- test_cmp marks.out marks.new'
+test_expect_success 'R: import to output marks works without any content' '
+ cat >input <<-EOF &&
+ feature import-marks=marks.out
+ feature export-marks=marks.new
+ EOF
-cat >input <<EOF
-feature import-marks=nonexistent.marks
-feature export-marks=marks.new
-EOF
+ cat input | git fast-import &&
+ test_cmp marks.out marks.new
+'
-test_expect_success \
- 'R: import marks prefers commandline marks file over the stream' \
- 'cat input | git fast-import --import-marks=marks.out &&
- test_cmp marks.out marks.new'
+test_expect_success 'R: import marks prefers commandline marks file over the stream' '
+ cat >input <<-EOF &&
+ feature import-marks=nonexistent.marks
+ feature export-marks=marks.new
+ EOF
+ cat input | git fast-import --import-marks=marks.out &&
+ test_cmp marks.out marks.new
+'
-cat >input <<EOF
-feature import-marks=nonexistent.marks
-feature export-marks=combined.marks
-EOF
test_expect_success 'R: multiple --import-marks= should be honoured' '
- head -n2 marks.out > one.marks &&
- tail -n +3 marks.out > two.marks &&
- git fast-import --import-marks=one.marks --import-marks=two.marks <input &&
- test_cmp marks.out combined.marks
-'
+ cat >input <<-EOF &&
+ feature import-marks=nonexistent.marks
+ feature export-marks=combined.marks
+ EOF
-cat >input <<EOF
-feature relative-marks
-feature import-marks=relative.in
-feature export-marks=relative.out
-EOF
+ head -n2 marks.out > one.marks &&
+ tail -n +3 marks.out > two.marks &&
+ git fast-import --import-marks=one.marks --import-marks=two.marks <input &&
+ test_cmp marks.out combined.marks
+'
test_expect_success 'R: feature relative-marks should be honoured' '
- mkdir -p .git/info/fast-import/ &&
- cp marks.new .git/info/fast-import/relative.in &&
- git fast-import <input &&
- test_cmp marks.new .git/info/fast-import/relative.out
-'
+ cat >input <<-EOF &&
+ feature relative-marks
+ feature import-marks=relative.in
+ feature export-marks=relative.out
+ EOF
-cat >input <<EOF
-feature relative-marks
-feature import-marks=relative.in
-feature no-relative-marks
-feature export-marks=non-relative.out
-EOF
+ mkdir -p .git/info/fast-import/ &&
+ cp marks.new .git/info/fast-import/relative.in &&
+ git fast-import <input &&
+ test_cmp marks.new .git/info/fast-import/relative.out
+'
test_expect_success 'R: feature no-relative-marks should be honoured' '
- git fast-import <input &&
- test_cmp marks.new non-relative.out
+ cat >input <<-EOF &&
+ feature relative-marks
+ feature import-marks=relative.in
+ feature no-relative-marks
+ feature export-marks=non-relative.out
+ EOF
+
+ git fast-import <input &&
+ test_cmp marks.new non-relative.out
'
test_expect_success 'R: feature ls supported' '
cat-blob $blob
EOF
test_cmp expect actual.3 &&
- test_cmp empty actual.1 &&
+ test_must_be_empty actual.1 &&
git fast-import 3>actual.3 >actual.1 <<-EOF &&
option cat-blob-fd=3
cat-blob $blob
EOF
- test_cmp empty actual.3 &&
+ test_must_be_empty actual.3 &&
test_cmp expect actual.1
'
test_cmp expect actual
'
-cat >input << EOF
-option git quiet
-blob
-data 3
-hi
+test_expect_success 'R: quiet option results in no stats being output' '
+ cat >input <<-EOF &&
+ option git quiet
+ blob
+ data 3
+ hi
-EOF
+ EOF
-test_expect_success 'R: quiet option results in no stats being output' '
- cat input | git fast-import 2> output &&
- test_cmp empty output
+ cat input | git fast-import 2> output &&
+ test_must_be_empty output
'
test_expect_success 'R: feature done means terminating "done" is mandatory' '
test_cmp expect actual
'
-cat >input <<EOF
-option git non-existing-option
-EOF
-
test_expect_success 'R: die on unknown option' '
- test_must_fail git fast-import <input
+ cat >input <<-EOF &&
+ option git non-existing-option
+ EOF
+
+ test_must_fail git fast-import <input
'
test_expect_success 'R: unknown commandline options are rejected' '\
- test_must_fail git fast-import --non-existing-option < /dev/null
+ test_must_fail git fast-import --non-existing-option < /dev/null
'
test_expect_success 'R: die on invalid option argument' '
test_must_fail git fast-import --depth="5 elephants" </dev/null
'
-cat >input <<EOF
-option non-existing-vcs non-existing-option
-EOF
-
test_expect_success 'R: ignore non-git options' '
- git fast-import <input
+ cat >input <<-EOF &&
+ option non-existing-vcs non-existing-option
+ EOF
+
+ git fast-import <input
'
##
## R: very large blobs
##
-blobsize=$((2*1024*1024 + 53))
-test-genrandom bar $blobsize >expect
-cat >input <<INPUT_END
-commit refs/heads/big-file
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-R - big file
-COMMIT
-
-M 644 inline big1
-data $blobsize
-INPUT_END
-cat expect >>input
-cat >>input <<INPUT_END
-M 644 inline big2
-data $blobsize
-INPUT_END
-cat expect >>input
-echo >>input
-
-test_expect_success \
- 'R: blob bigger than threshold' \
- 'test_create_repo R &&
- git --git-dir=R/.git fast-import --big-file-threshold=1 <input'
+test_expect_success 'R: blob bigger than threshold' '
+ blobsize=$((2*1024*1024 + 53)) &&
+ test-genrandom bar $blobsize >expect &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/big-file
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ R - big file
+ COMMIT
+
+ M 644 inline big1
+ data $blobsize
+ INPUT_END
+ cat expect >>input &&
+ cat >>input <<-INPUT_END &&
+ M 644 inline big2
+ data $blobsize
+ INPUT_END
+ cat expect >>input &&
+ echo >>input &&
+
+ test_create_repo R &&
+ git --git-dir=R/.git fast-import --big-file-threshold=1 <input
+'
test_expect_success 'R: verify created pack' '
(
)
'
-test_expect_success \
- 'R: verify written objects' \
- 'git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
- test_cmp_bin expect actual &&
- a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
- b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
- test $a = $b'
-test_expect_success \
- 'R: blob appears only once' \
- 'n=$(grep $a verify | wc -l) &&
- test 1 = $n'
+test_expect_success 'R: verify written objects' '
+ git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
+ test_cmp_bin expect actual &&
+ a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
+ b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
+ test $a = $b
+'
+
+test_expect_success 'R: blob appears only once' '
+ n=$(grep $a verify | wc -l) &&
+ test 1 = $n
+'
###
### series S
#
# Invalid dataref ..
#
-test_tick
-
-cat >input <<INPUT_END
-commit refs/heads/S
-mark :301
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-commit 1
-COMMIT
-M 100644 inline hello.c
-data <<BLOB
-blob 1
-BLOB
-
-commit refs/heads/S
-mark :302
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-commit 2
-COMMIT
-from :301
-M 100644 inline hello.c
-data <<BLOB
-blob 2
-BLOB
-
-blob
-mark :403
-data <<BLOB
-blob 3
-BLOB
-
-blob
-mark :202
-data <<BLOB
-note 2
-BLOB
-INPUT_END
-
test_expect_success 'S: initialize for S tests' '
+ test_tick &&
+
+ cat >input <<-INPUT_END &&
+ commit refs/heads/S
+ mark :301
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit 1
+ COMMIT
+ M 100644 inline hello.c
+ data <<BLOB
+ blob 1
+ BLOB
+
+ commit refs/heads/S
+ mark :302
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit 2
+ COMMIT
+ from :301
+ M 100644 inline hello.c
+ data <<BLOB
+ blob 2
+ BLOB
+
+ blob
+ mark :403
+ data <<BLOB
+ blob 3
+ BLOB
+
+ blob
+ mark :202
+ data <<BLOB
+ note 2
+ BLOB
+ INPUT_END
+
git fast-import --export-marks=marks <input
'
### series U (filedelete)
###
-cat >input <<INPUT_END
-commit refs/heads/U
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-test setup
-COMMIT
-M 100644 inline hello.c
-data <<BLOB
-blob 1
-BLOB
-M 100644 inline good/night.txt
-data <<BLOB
-sleep well
-BLOB
-M 100644 inline good/bye.txt
-data <<BLOB
-au revoir
-BLOB
-
-INPUT_END
-
test_expect_success 'U: initialize for U tests' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/U
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ test setup
+ COMMIT
+ M 100644 inline hello.c
+ data <<BLOB
+ blob 1
+ BLOB
+ M 100644 inline good/night.txt
+ data <<BLOB
+ sleep well
+ BLOB
+ M 100644 inline good/bye.txt
+ data <<BLOB
+ au revoir
+ BLOB
+
+ INPUT_END
+
git fast-import <input
'
-cat >input <<INPUT_END
-commit refs/heads/U
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-delete good/night.txt
-COMMIT
-from refs/heads/U^0
-D good/night.txt
+test_expect_success 'U: filedelete file succeeds' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/U
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ delete good/night.txt
+ COMMIT
+ from refs/heads/U^0
+ D good/night.txt
-INPUT_END
+ INPUT_END
-test_expect_success 'U: filedelete file succeeds' '
git fast-import <input
'
-cat >expect <<EOF
-:100644 000000 2907ebb4bf85d91bf0716bb3bd8a68ef48d6da76 0000000000000000000000000000000000000000 D good/night.txt
-EOF
+test_expect_success 'U: validate file delete result' '
+ cat >expect <<-EOF &&
+ :100644 000000 2907ebb4bf85d91bf0716bb3bd8a68ef48d6da76 0000000000000000000000000000000000000000 D good/night.txt
+ EOF
-git diff-tree -M -r U^1 U >actual
+ git diff-tree -M -r U^1 U >actual &&
-test_expect_success 'U: validate file delete result' '
compare_diff_raw expect actual
'
-cat >input <<INPUT_END
-commit refs/heads/U
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-delete good dir
-COMMIT
-from refs/heads/U^0
-D good
+test_expect_success 'U: filedelete directory succeeds' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/U
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ delete good dir
+ COMMIT
+ from refs/heads/U^0
+ D good
-INPUT_END
+ INPUT_END
-test_expect_success 'U: filedelete directory succeeds' '
git fast-import <input
'
-cat >expect <<EOF
-:100644 000000 69cb75792f55123d8389c156b0b41c2ff00ed507 0000000000000000000000000000000000000000 D good/bye.txt
-EOF
+test_expect_success 'U: validate directory delete result' '
+ cat >expect <<-EOF &&
+ :100644 000000 69cb75792f55123d8389c156b0b41c2ff00ed507 0000000000000000000000000000000000000000 D good/bye.txt
+ EOF
-git diff-tree -M -r U^1 U >actual
+ git diff-tree -M -r U^1 U >actual &&
-test_expect_success 'U: validate directory delete result' '
compare_diff_raw expect actual
'
-cat >input <<INPUT_END
-commit refs/heads/U
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-must succeed
-COMMIT
-from refs/heads/U^0
-D ""
+test_expect_success 'U: filedelete root succeeds' '
+ cat >input <<-INPUT_END &&
+ commit refs/heads/U
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ must succeed
+ COMMIT
+ from refs/heads/U^0
+ D ""
-INPUT_END
+ INPUT_END
-test_expect_success 'U: filedelete root succeeds' '
- git fast-import <input
+ git fast-import <input
'
-cat >expect <<EOF
-:100644 000000 c18147dc648481eeb65dc5e66628429a64843327 0000000000000000000000000000000000000000 D hello.c
-EOF
+test_expect_success 'U: validate root delete result' '
+ cat >expect <<-EOF &&
+ :100644 000000 c18147dc648481eeb65dc5e66628429a64843327 0000000000000000000000000000000000000000 D hello.c
+ EOF
-git diff-tree -M -r U^1 U >actual
+ git diff-tree -M -r U^1 U >actual &&
-test_expect_success 'U: validate root delete result' '
compare_diff_raw expect actual
'
)
'
+test_expect_success 'submit from detached head' '
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ git checkout p4/master &&
+ >detached_head_test &&
+ git add detached_head_test &&
+ git commit -m "add detached_head" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit &&
+ git p4 rebase &&
+ git log p4/master | grep detached_head
+ )
+'
+
test_expect_success 'kill p4d' '
kill_p4d
'
(
cd "$cli" &&
p4 revert desc6 &&
- rm desc6
+ rm -f desc6
)
'
test_cmp expected "$actual"
'
-test_expect_success 'prompt - dirty status indicator - before root commit' '
- printf " (master #)" >expected &&
+test_expect_success 'prompt - dirty status indicator - orphan branch - clean' '
+ printf " (orphan #)" >expected &&
+ test_when_finished "git checkout master" &&
+ git checkout --orphan orphan &&
+ git reset --hard &&
+ (
+ GIT_PS1_SHOWDIRTYSTATE=y &&
+ __git_ps1 >"$actual"
+ ) &&
+ test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - dirty status indicator - orphan branch - dirty index' '
+ printf " (orphan +)" >expected &&
+ test_when_finished "git checkout master" &&
+ git checkout --orphan orphan &&
+ (
+ GIT_PS1_SHOWDIRTYSTATE=y &&
+ __git_ps1 >"$actual"
+ ) &&
+ test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - dirty status indicator - orphan branch - dirty index and worktree' '
+ printf " (orphan *+)" >expected &&
+ test_when_finished "git checkout master" &&
+ git checkout --orphan orphan &&
+ >file &&
(
GIT_PS1_SHOWDIRTYSTATE=y &&
- cd otherrepo &&
__git_ps1 >"$actual"
) &&
test_cmp expected "$actual"
#include "submodule.h"
#include "string-list.h"
#include "sha1-array.h"
+#include "sigchain.h"
/* rsync support */
return -1;
}
+ sigchain_push(SIGPIPE, SIG_IGN);
+
strbuf_init(&buf, 256);
for (r = remote_refs; r; r = r->next) {
r->peer_ref->name, sha1_to_hex(r->new_sha1),
r->name, sha1_to_hex(r->old_sha1));
- if (write_in_full(proc.in, buf.buf, buf.len) != buf.len) {
- ret = -1;
+ if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
+ /* We do not mind if a hook does not read all refs. */
+ if (errno != EPIPE)
+ ret = -1;
break;
}
}
if (!ret)
ret = x;
+ sigchain_pop(SIGPIPE);
+
x = finish_command(&proc);
if (!ret)
ret = x;
}
/* return non-zero if the ref is hidden, otherwise 0 */
-static int mark_our_ref(const char *refname, const struct object_id *oid)
+static int mark_our_ref(const char *refname, const char *refname_full,
+ const struct object_id *oid)
{
struct object *o = lookup_unknown_object(oid->hash);
- if (ref_is_hidden(refname)) {
+ if (ref_is_hidden(refname, refname_full)) {
o->flags |= HIDDEN_REF;
return 1;
}
return 0;
}
-static int check_ref(const char *refname, const struct object_id *oid,
+static int check_ref(const char *refname_full, const struct object_id *oid,
int flag, void *cb_data)
{
- mark_our_ref(refname, oid);
+ const char *refname = strip_namespace(refname_full);
+
+ mark_our_ref(refname, refname_full, oid);
return 0;
}
const char *refname_nons = strip_namespace(refname);
struct object_id peeled;
- if (mark_our_ref(refname, oid))
+ if (mark_our_ref(refname_nons, refname, oid))
return 0;
if (capabilities) {
target += strlen(" to ");
strbuf_reset(&cb->buf);
hashcpy(cb->nsha1, nsha1);
- for (end = target; *end && *end != '\n'; end++)
- ;
- if (!memcmp(target, "HEAD", end - target)) {
+ end = strchrnul(target, '\n');
+ strbuf_add(&cb->buf, target, end - target);
+ if (!strcmp(cb->buf.buf, "HEAD")) {
/* HEAD is relative. Resolve it to the right reflog entry. */
+ strbuf_reset(&cb->buf);
strbuf_addstr(&cb->buf,
find_unique_abbrev(nsha1, DEFAULT_ABBREV));
- return 1;
}
- strbuf_add(&cb->buf, target, end - target);
return 1;
}