--- /dev/null
+Git 2.18 Release Notes
+======================
+
+Updates since v2.17
+-------------------
+
+UI, Workflows & Features
+
+ * Rename detection logic in "diff" family that is used in "merge" has
+ learned to guess when all of x/a, x/b and x/c have moved to z/a,
+ z/b and z/c, it is likely that x/d added in the meantime would also
+ want to move to z/d by taking the hint that the entire directory
+ 'x' moved to 'z'. A bug causing dirty files involved in a rename
+ to be overwritten during merge has also been fixed as part of this
+ work.
+
+ * "git filter-branch" learned to use a different exit code to allow
+ the callers to tell the case where there was no new commits to
+ rewrite from other error cases.
+
+ * When built with more recent cURL, GIT_SSL_VERSION can now specify
+ "tlsv1.3" as its value.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * A "git fetch" from a repository with insane number of refs into a
+ repository that is already up-to-date still wasted too many cycles
+ making many lstat(2) calls to see if these objects at the tips
+ exist as loose objects locally. These lstat(2) calls are optimized
+ away by enumerating all loose objects beforehand.
+ It is unknown if the new strategy negatively affects existing use
+ cases, fetching into a repository with many loose objects from a
+ repository with small number of refs.
+
+ * Git can be built to use either v1 or v2 of the PCRE library, and so
+ far, the build-time configuration USE_LIBPCRE=YesPlease instructed
+ the build procedure to use v1, but now it means v2. USE_LIBPCRE1
+ and USE_LIBPCRE2 can be used to explicitly choose which version to
+ use, as before.
+
+ * The build procedure learned to optionally use symbolic links
+ (instead of hardlinks and copies) to install "git-foo" for built-in
+ commands, whose binaries are all identical.
+
+ * Conversion from uchar[20] to struct object_id continues.
+
+ * The way "git worktree prune" worked internally has been simplified,
+ by assuming how "git worktree move" moves an existing worktree to a
+ different place.
+
+ * Code clean-up for the "repository" abstraction.
+ (merge 00a3da2a13 nd/remove-ignore-env-field later to maint).
+
+ * Code to find the length to uniquely abbreviate object names based
+ on packfile content, which is a relatively recent addtion, has been
+ optimized to use the same fan-out table.
+
+ * The mechanism to use parse-options API to automate the command line
+ completion continues to get extended and polished.
+
+ * Copies of old scripted Porcelain commands in contrib/examples/ have
+ been removed.
+
+ * Some tests that rely on the exact hardcoded values of object names
+ have been updated in preparation for hash function migration.
+
+ * Perf-test update.
+
+ * Test helper update.
+
+ * The effort continues to refactor the internal global data structure
+ to make it possible to open multiple repositories, work with and
+ then close them,
+
+ * Small test-helper programs have been consolidated into a single
+ binary.
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v2.17
+-----------------
+
+ * "git shortlog cruft" aborted with a BUG message when run outside a
+ Git repository. The command has been taught to complain about
+ extra and unwanted arguments on its command line instead in such a
+ case.
+ (merge 4aa0161e83 ma/shortlog-revparse later to maint).
+
+ * "git stash push -u -- <pathspec>" gave an unnecessary and confusing
+ error message when there was no tracked files that match the
+ <pathspec>, which has been fixed.
+ (merge 353278687e tg/stash-untracked-with-pathspec-fix later to maint).
+
+ * "git tag --contains no-such-commit" gave a full list of options
+ after giving an error message.
+ (merge 3bb0923f06 ps/contains-id-error-message later to maint).
+
+ * "diff-highlight" filter (in contrib/) learned to undertand "git log
+ --graph" output better.
+ (merge 4551fbba14 jk/diff-highlight-graph-fix later to maint).
+
+ * when refs that do not point at committish are given, "git
+ filter-branch" gave a misleading error messages. This has been
+ corrected.
+ (merge f78ab355e7 yk/filter-branch-non-committish-refs later to maint).
+
+ * "git submodule status" misbehaved on a submodule that has been
+ removed from the working tree.
+ (merge 74b6bda32f rs/status-with-removed-submodule later to maint).
+
+ * When credential helper exits very quickly without reading its
+ input, it used to cause Git to die with SIGPIPE, which has been
+ fixed.
+ (merge a0d51e8d0e eb/cred-helper-ignore-sigpipe later to maint).
+
+ * Other minor doc, test and build updates and code cleanups.
+ (merge 248f66ed8e nd/trace-with-env later to maint).
+ (merge 14ced5562c ys/bisect-object-id-missing-conversion-fix later to maint).
+ (merge 5988eb631a ab/doc-hash-brokenness later to maint).
+ (merge a4d4e32a70 pk/test-avoid-pipe-hiding-exit-status later to maint).
- tlsv1.0
- tlsv1.1
- tlsv1.2
+ - tlsv1.3
+
Can be overridden by the `GIT_SSL_VERSION` environment variable.
was not excluded.
+EXIT STATUS
+-----------
+
+On success, the exit status is `0`. If the filter can't find any commits to
+rewrite, the exit status is `2`. On any other error, the exit status may be
+any other non-zero value.
+
+
Examples
--------
-----------
Runs a number of housekeeping tasks within the current repository,
such as compressing file revisions (to reduce disk space and increase
-performance) and removing unreachable objects which may have been
-created from prior invocations of 'git add'.
+performance), removing unreachable objects which may have been
+created from prior invocations of 'git add', packing refs, pruning
+reflog, rerere metadata or stale working trees.
Users are encouraged to run this task on a regular basis within
each repository to maintain good disk space utilization and good
With this option, 'git gc' checks whether any housekeeping is
required; if not, it exits without performing any work.
Some git commands run `git gc --auto` after performing
- operations that could create many loose objects.
+ operations that could create many loose objects. Housekeeping
+ is required if there are too many loose objects or too many
+ packs in the repository.
+
-Housekeeping is required if there are too many loose objects or
-too many packs in the repository. If the number of loose objects
-exceeds the value of the `gc.auto` configuration variable, then
-all loose objects are combined into a single pack using
-`git repack -d -l`. Setting the value of `gc.auto` to 0
-disables automatic packing of loose objects.
+If the number of loose objects exceeds the value of the `gc.auto`
+configuration variable, then all loose objects are combined into a
+single pack using `git repack -d -l`. Setting the value of `gc.auto`
+to 0 disables automatic packing of loose objects.
+
If the number of packs exceeds the value of `gc.autoPackLimit`,
then existing packs (except those marked with a `.keep` file)
are consolidated into a single pack by using the `-A` option of
'git repack'. Setting `gc.autoPackLimit` to 0 disables
automatic consolidation of packs.
++
+If houskeeping is required due to many loose objects or packs, all
+other housekeeping tasks (e.g. rerere, working trees, reflog...) will
+be performed as well.
+
--prune=<date>::
Prune loose objects older than date (default is 2 weeks ago,
the unreferenced loose objects have to be before they are pruned. The
default is "2 weeks ago".
+Optional configuration variable `gc.worktreePruneExpire` controls how
+old a stale working tree should be before `git worktree prune` deletes
+it. Default is "3 months ago".
+
Notes
-----
SYNOPSIS
--------
[verse]
-git log --pretty=short | 'git shortlog' [<options>]
'git shortlog' [<options>] [<revision range>] [[\--] <path>...]
+git log --pretty=short | 'git shortlog' [<options>]
DESCRIPTION
-----------
or manually by `git worktree prune`. The file may contain a string
explaining why the repository is locked.
-worktrees/<id>/link::
- If this file exists, it is a hard link to the linked .git
- file. It is used to detect if the linked repository is
- manually removed.
-
SEE ALSO
--------
linkgit:git-init[1],
# now add our object data
cat object >>tmp.pack
# and then append the pack trailer
- /path/to/git.git/test-sha1 -b <tmp.pack >trailer
+ /path/to/git.git/t/helper/test-tool sha1 -b <tmp.pack >trailer
cat trailer >>tmp.pack
------------
address stored content.
Over time some flaws in SHA-1 have been discovered by security
-researchers. https://shattered.io demonstrated a practical SHA-1 hash
-collision. As a result, SHA-1 cannot be considered cryptographically
-secure any more. This impacts the communication of hash values because
-we cannot trust that a given hash value represents the known good
-version of content that the speaker intended.
+researchers. On 23 February 2017 the SHAttered attack
+(https://shattered.io) demonstrated a practical SHA-1 hash collision.
+
+Git v2.13.0 and later subsequently moved to a hardened SHA-1
+implementation by default, which isn't vulnerable to the SHAttered
+attack.
+
+Thus Git has in effect already migrated to a new hash that isn't SHA-1
+and doesn't share its vulnerabilities, its new hash function just
+happens to produce exactly the same output for all known inputs,
+except two PDFs published by the SHAttered researchers, and the new
+implementation (written by those researchers) claims to detect future
+cryptanalytic collision attacks.
+
+Regardless, it's considered prudent to move past any variant of SHA-1
+to a new hash. There's no guarantee that future attacks on SHA-1 won't
+be published in the future, and those attacks may not have viable
+mitigations.
+
+If SHA-1 and its variants were to be truly broken, Git's hash function
+could not be considered cryptographically secure any more. This would
+impact the communication of hash values because we could not trust
+that a given hash value represented the known good version of content
+that the speaker intended.
SHA-1 still possesses the other properties such as fast object lookup
and safe error checking, but other hash functions are equally suitable
objectFormat = newhash
compatObjectFormat = sha1
-Specifying a repository format extension ensures that versions of Git
-not aware of NewHash do not try to operate on these repositories,
-instead producing an error message:
+The combination of setting `core.repositoryFormatVersion=1` and
+populating `extensions.*` ensures that all versions of Git later than
+`v0.99.9l` will die instead of trying to operate on the NewHash
+repository, instead producing an error message.
+ # Between v0.99.9l and v2.7.0
+ $ git status
+ fatal: Expected git repo version <= 0, found 1
+ # After v2.7.0
$ git status
fatal: unknown repository extensions found:
objectformat
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.17.0
+DEF_VER=v2.17.GIT
LF='
'
# Perl-compatible regular expressions instead of standard or extended
# POSIX regular expressions.
#
-# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
-# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
-# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
-# default in future releases.
+# USE_LIBPCRE is a synonym for USE_LIBPCRE2, define USE_LIBPCRE1
+# instead if you'd like to use the legacy version 1 of the PCRE
+# library. Support for version 1 will likely be removed in some future
+# release of Git, as upstream has all but abandoned it.
#
# When using USE_LIBPCRE1, define NO_LIBPCRE1_JIT if the PCRE v1
# library is compiled without --enable-jit. We will auto-detect
# when hardlinking a file to another name and unlinking the original file right
# away (some NTFS drivers seem to zero the contents in that scenario).
#
+# Define INSTALL_SYMLINKS if you prefer to have everything that can be
+# symlinked between bin/ and libexec/ to use relative symlinks between
+# the two. This option overrides NO_CROSS_DIRECTORY_HARDLINKS and
+# NO_INSTALL_HARDLINKS which will also use symlinking by indirection
+# within the same directory in some cases, INSTALL_SYMLINKS will
+# always symlink to the final target directly.
+#
# Define NO_CROSS_DIRECTORY_HARDLINKS if you plan to distribute the installed
# programs as a tar, where bin/ and libexec/ might be on different file systems.
#
# This can help installing the suite in a relocatable way.
prefix = $(HOME)
-bindir_relative = bin
-bindir = $(prefix)/$(bindir_relative)
+bindir = $(prefix)/bin
mandir = $(prefix)/share/man
infodir = $(prefix)/share/info
gitexecdir = libexec/git-core
# DESTDIR =
pathsep = :
+bindir_relative = $(patsubst $(prefix)/%,%,$(bindir))
mandir_relative = $(patsubst $(prefix)/%,%,$(mandir))
infodir_relative = $(patsubst $(prefix)/%,%,$(infodir))
+gitexecdir_relative = $(patsubst $(prefix)/%,%,$(gitexecdir))
htmldir_relative = $(patsubst $(prefix)/%,%,$(htmldir))
export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir
SCRIPT_PYTHON =
SCRIPT_SH =
SCRIPT_LIB =
+TEST_BUILTINS_OBJS =
TEST_PROGRAMS_NEED_X =
# Having this variable in your environment would break pipelines because
PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
-TEST_PROGRAMS_NEED_X += test-chmtime
-TEST_PROGRAMS_NEED_X += test-ctype
-TEST_PROGRAMS_NEED_X += test-config
-TEST_PROGRAMS_NEED_X += test-date
-TEST_PROGRAMS_NEED_X += test-delta
-TEST_PROGRAMS_NEED_X += test-drop-caches
-TEST_PROGRAMS_NEED_X += test-dump-cache-tree
+TEST_BUILTINS_OBJS += test-chmtime.o
+TEST_BUILTINS_OBJS += test-config.o
+TEST_BUILTINS_OBJS += test-ctype.o
+TEST_BUILTINS_OBJS += test-date.o
+TEST_BUILTINS_OBJS += test-delta.o
+TEST_BUILTINS_OBJS += test-drop-caches.o
+TEST_BUILTINS_OBJS += test-dump-cache-tree.o
+TEST_BUILTINS_OBJS += test-dump-split-index.o
+TEST_BUILTINS_OBJS += test-example-decorate.o
+TEST_BUILTINS_OBJS += test-genrandom.o
+TEST_BUILTINS_OBJS += test-hashmap.o
+TEST_BUILTINS_OBJS += test-index-version.o
+TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o
+TEST_BUILTINS_OBJS += test-match-trees.o
+TEST_BUILTINS_OBJS += test-mergesort.o
+TEST_BUILTINS_OBJS += test-mktemp.o
+TEST_BUILTINS_OBJS += test-online-cpus.o
+TEST_BUILTINS_OBJS += test-path-utils.o
+TEST_BUILTINS_OBJS += test-prio-queue.o
+TEST_BUILTINS_OBJS += test-read-cache.o
+TEST_BUILTINS_OBJS += test-ref-store.o
+TEST_BUILTINS_OBJS += test-regex.o
+TEST_BUILTINS_OBJS += test-revision-walking.o
+TEST_BUILTINS_OBJS += test-run-command.o
+TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
+TEST_BUILTINS_OBJS += test-sha1-array.o
+TEST_BUILTINS_OBJS += test-sha1.o
+TEST_BUILTINS_OBJS += test-sigchain.o
+TEST_BUILTINS_OBJS += test-strcmp-offset.o
+TEST_BUILTINS_OBJS += test-string-list.o
+TEST_BUILTINS_OBJS += test-submodule-config.o
+TEST_BUILTINS_OBJS += test-subprocess.o
+TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
+TEST_BUILTINS_OBJS += test-wildmatch.o
+TEST_BUILTINS_OBJS += test-write-cache.o
+
TEST_PROGRAMS_NEED_X += test-dump-fsmonitor
-TEST_PROGRAMS_NEED_X += test-dump-split-index
TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
-TEST_PROGRAMS_NEED_X += test-example-decorate
TEST_PROGRAMS_NEED_X += test-fake-ssh
-TEST_PROGRAMS_NEED_X += test-genrandom
-TEST_PROGRAMS_NEED_X += test-hashmap
-TEST_PROGRAMS_NEED_X += test-index-version
-TEST_PROGRAMS_NEED_X += test-lazy-init-name-hash
TEST_PROGRAMS_NEED_X += test-line-buffer
-TEST_PROGRAMS_NEED_X += test-match-trees
-TEST_PROGRAMS_NEED_X += test-mergesort
-TEST_PROGRAMS_NEED_X += test-mktemp
-TEST_PROGRAMS_NEED_X += test-online-cpus
TEST_PROGRAMS_NEED_X += test-parse-options
-TEST_PROGRAMS_NEED_X += test-path-utils
-TEST_PROGRAMS_NEED_X += test-prio-queue
-TEST_PROGRAMS_NEED_X += test-read-cache
-TEST_PROGRAMS_NEED_X += test-write-cache
-TEST_PROGRAMS_NEED_X += test-ref-store
-TEST_PROGRAMS_NEED_X += test-regex
-TEST_PROGRAMS_NEED_X += test-revision-walking
-TEST_PROGRAMS_NEED_X += test-run-command
-TEST_PROGRAMS_NEED_X += test-scrap-cache-tree
-TEST_PROGRAMS_NEED_X += test-sha1
-TEST_PROGRAMS_NEED_X += test-sha1-array
-TEST_PROGRAMS_NEED_X += test-sigchain
-TEST_PROGRAMS_NEED_X += test-strcmp-offset
-TEST_PROGRAMS_NEED_X += test-string-list
-TEST_PROGRAMS_NEED_X += test-submodule-config
-TEST_PROGRAMS_NEED_X += test-subprocess
TEST_PROGRAMS_NEED_X += test-svn-fe
-TEST_PROGRAMS_NEED_X += test-urlmatch-normalization
-TEST_PROGRAMS_NEED_X += test-wildmatch
+TEST_PROGRAMS_NEED_X += test-tool
TEST_PROGRAMS = $(patsubst %,t/helper/%$X,$(TEST_PROGRAMS_NEED_X))
COMPAT_OBJS += compat/basename.o
endif
-USE_LIBPCRE1 ?= $(USE_LIBPCRE)
+USE_LIBPCRE2 ?= $(USE_LIBPCRE)
-ifneq (,$(USE_LIBPCRE1))
- ifdef USE_LIBPCRE2
-$(error Only set USE_LIBPCRE1 (or its alias USE_LIBPCRE) or USE_LIBPCRE2, not both!)
+ifneq (,$(USE_LIBPCRE2))
+ ifdef USE_LIBPCRE1
+$(error Only set USE_LIBPCRE2 (or its alias USE_LIBPCRE) or USE_LIBPCRE1, not both!)
endif
+ BASIC_CFLAGS += -DUSE_LIBPCRE2
+ EXTLIBS += -lpcre2-8
+endif
+
+ifdef USE_LIBPCRE1
BASIC_CFLAGS += -DUSE_LIBPCRE1
EXTLIBS += -lpcre
endif
endif
-ifdef USE_LIBPCRE2
- BASIC_CFLAGS += -DUSE_LIBPCRE2
- EXTLIBS += -lpcre2-8
-endif
-
ifdef LIBPCREDIR
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
perllibdir_SQ = $(subst ','\'',$(perllibdir))
localedir_SQ = $(subst ','\'',$(localedir))
gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
+gitexecdir_relative_SQ = $(subst ','\'',$(gitexecdir_relative))
template_dir_SQ = $(subst ','\'',$(template_dir))
htmldir_relative_SQ = $(subst ','\'',$(htmldir_relative))
prefix_SQ = $(subst ','\'',$(prefix))
VCSSVN_OBJS += vcs-svn/svndiff.o
VCSSVN_OBJS += vcs-svn/svndump.o
-TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS))
+TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
$(XDIFF_OBJS) \
$(VCSSVN_OBJS) \
.PRECIOUS: $(TEST_OBJS)
+t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
+
t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
-check-sha1:: t/helper/test-sha1$X
+check-sha1:: t/helper/test-tool$X
t/helper/test-sha1.sh
SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ))
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
+ destdir_from_execdir_SQ=$$(echo '$(gitexecdir_relative_SQ)' | sed -e 's|[^/][^/]*|..|g') && \
{ test "$$bindir/" = "$$execdir/" || \
for p in git$X $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \
$(RM) "$$execdir/$$p" && \
- test -z "$(NO_INSTALL_HARDLINKS)$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
- ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \
- cp "$$bindir/$$p" "$$execdir/$$p" || exit; \
+ test -n "$(INSTALL_SYMLINKS)" && \
+ ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/$$p" "$$execdir/$$p" || \
+ { test -z "$(NO_INSTALL_HARDLINKS)$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
+ ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \
+ cp "$$bindir/$$p" "$$execdir/$$p" || exit; } \
done; \
} && \
for p in $(filter $(install_bindir_programs),$(BUILT_INS)); do \
$(RM) "$$bindir/$$p" && \
- test -z "$(NO_INSTALL_HARDLINKS)" && \
- ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
- ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
- cp "$$bindir/git$X" "$$bindir/$$p" || exit; \
+ test -n "$(INSTALL_SYMLINKS)" && \
+ ln -s "git$X" "$$bindir/$$p" || \
+ { test -z "$(NO_INSTALL_HARDLINKS)" && \
+ ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
+ ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
+ cp "$$bindir/git$X" "$$bindir/$$p" || exit; } \
done && \
for p in $(BUILT_INS); do \
$(RM) "$$execdir/$$p" && \
- test -z "$(NO_INSTALL_HARDLINKS)" && \
- ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
- ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
- cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
+ test -n "$(INSTALL_SYMLINKS)" && \
+ ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/git$X" "$$execdir/$$p" || \
+ { test -z "$(NO_INSTALL_HARDLINKS)" && \
+ ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
+ ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
+ cp "$$execdir/git$X" "$$execdir/$$p" || exit; } \
done && \
remote_curl_aliases="$(REMOTE_CURL_ALIASES)" && \
for p in $$remote_curl_aliases; do \
$(RM) "$$execdir/$$p" && \
- test -z "$(NO_INSTALL_HARDLINKS)" && \
- ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
- ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
- cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
+ test -n "$(INSTALL_SYMLINKS)" && \
+ ln -s "git-remote-http$X" "$$execdir/$$p" || \
+ { test -z "$(NO_INSTALL_HARDLINKS)" && \
+ ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+ ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+ cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; } \
done && \
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
-Documentation/RelNotes/2.17.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.18.0.txt
\ No newline at end of file
unsigned long size;
char *result;
- result = read_sha1_file(oid.hash, &type, &size);
+ result = read_object_file(&oid, &type, &size);
if (!result)
return error(_("the necessary postimage %s for "
"'%s' cannot be read"),
unsigned long sz;
char *result;
- result = read_sha1_file(oid->hash, &type, &sz);
+ result = read_object_file(oid, &type, &sz);
if (!result)
return -1;
/* XXX read_sha1_file NUL-terminates */
* queues up writes, so that all our write(2) calls write exactly one
* full block; pads writes to RECORDSIZE
*/
-static int stream_blocked(const unsigned char *sha1)
+static int stream_blocked(const struct object_id *oid)
{
struct git_istream *st;
enum object_type type;
char buf[BLOCKSIZE];
ssize_t readlen;
- st = open_istream(sha1, &type, &sz, NULL);
+ st = open_istream(oid, &type, &sz, NULL);
if (!st)
- return error("cannot stream blob %s", sha1_to_hex(sha1));
+ return error("cannot stream blob %s", oid_to_hex(oid));
for (;;) {
readlen = read_istream(st, buf, sizeof(buf));
if (readlen <= 0)
}
static void write_extended_header(struct archiver_args *args,
- const unsigned char *sha1,
+ const struct object_id *oid,
const void *buffer, unsigned long size)
{
struct ustar_header header;
memset(&header, 0, sizeof(header));
*header.typeflag = TYPEFLAG_EXT_HEADER;
mode = 0100666;
- xsnprintf(header.name, sizeof(header.name), "%s.paxheader", sha1_to_hex(sha1));
+ xsnprintf(header.name, sizeof(header.name), "%s.paxheader", oid_to_hex(oid));
prepare_header(args, &header, mode, size);
write_blocked(&header, sizeof(header));
write_blocked(buffer, size);
}
static int write_tar_entry(struct archiver_args *args,
- const unsigned char *sha1,
+ const struct object_id *oid,
const char *path, size_t pathlen,
unsigned int mode)
{
mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
} else {
return error("unsupported file mode: 0%o (SHA1: %s)",
- mode, sha1_to_hex(sha1));
+ mode, oid_to_hex(oid));
}
if (pathlen > sizeof(header.name)) {
size_t plen = get_path_prefix(path, pathlen,
memcpy(header.name, path + plen + 1, rest);
} else {
xsnprintf(header.name, sizeof(header.name), "%s.data",
- sha1_to_hex(sha1));
+ oid_to_hex(oid));
strbuf_append_ext_header(&ext_header, "path",
path, pathlen);
}
memcpy(header.name, path, pathlen);
if (S_ISREG(mode) && !args->convert &&
- sha1_object_info(sha1, &size) == OBJ_BLOB &&
+ oid_object_info(oid, &size) == OBJ_BLOB &&
size > big_file_threshold)
buffer = NULL;
else if (S_ISLNK(mode) || S_ISREG(mode)) {
enum object_type type;
- buffer = sha1_file_to_archive(args, path, sha1, old_mode, &type, &size);
+ buffer = object_file_to_archive(args, path, oid, old_mode, &type, &size);
if (!buffer)
- return error("cannot read %s", sha1_to_hex(sha1));
+ return error("cannot read %s", oid_to_hex(oid));
} else {
buffer = NULL;
size = 0;
if (S_ISLNK(mode)) {
if (size > sizeof(header.linkname)) {
xsnprintf(header.linkname, sizeof(header.linkname),
- "see %s.paxheader", sha1_to_hex(sha1));
+ "see %s.paxheader", oid_to_hex(oid));
strbuf_append_ext_header(&ext_header, "linkpath",
buffer, size);
} else
prepare_header(args, &header, mode, size_in_header);
if (ext_header.len > 0) {
- write_extended_header(args, sha1, ext_header.buf,
+ write_extended_header(args, oid, ext_header.buf,
ext_header.len);
}
strbuf_release(&ext_header);
if (buffer)
write_blocked(buffer, size);
else
- err = stream_blocked(sha1);
+ err = stream_blocked(oid);
}
free(buffer);
return err;
#define STREAM_BUFFER_SIZE (1024 * 16)
static int write_zip_entry(struct archiver_args *args,
- const unsigned char *sha1,
+ const struct object_id *oid,
const char *path, size_t pathlen,
unsigned int mode)
{
if (pathlen > 0xffff) {
return error("path too long (%d chars, SHA1: %s): %s",
- (int)pathlen, sha1_to_hex(sha1), path);
+ (int)pathlen, oid_to_hex(oid), path);
}
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
compressed_size = 0;
buffer = NULL;
} else if (S_ISREG(mode) || S_ISLNK(mode)) {
- enum object_type type = sha1_object_info(sha1, &size);
+ enum object_type type = oid_object_info(oid, &size);
method = 0;
attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
size > big_file_threshold) {
- stream = open_istream(sha1, &type, &size, NULL);
+ stream = open_istream(oid, &type, &size, NULL);
if (!stream)
return error("cannot stream blob %s",
- sha1_to_hex(sha1));
+ oid_to_hex(oid));
flags |= ZIP_STREAM;
out = buffer = NULL;
} else {
- buffer = sha1_file_to_archive(args, path, sha1, mode,
- &type, &size);
+ buffer = object_file_to_archive(args, path, oid, mode,
+ &type, &size);
if (!buffer)
return error("cannot read %s",
- sha1_to_hex(sha1));
+ oid_to_hex(oid));
crc = crc32(crc, buffer, size);
is_binary = entry_is_binary(path_without_prefix,
buffer, size);
compressed_size = (method == 0) ? size : 0;
} else {
return error("unsupported file mode: 0%o (SHA1: %s)", mode,
- sha1_to_hex(sha1));
+ oid_to_hex(oid));
}
if (creator_version > max_creator_version)
free(to_free);
}
-void *sha1_file_to_archive(const struct archiver_args *args,
- const char *path, const unsigned char *sha1,
- unsigned int mode, enum object_type *type,
- unsigned long *sizep)
+void *object_file_to_archive(const struct archiver_args *args,
+ const char *path, const struct object_id *oid,
+ unsigned int mode, enum object_type *type,
+ unsigned long *sizep)
{
void *buffer;
const struct commit *commit = args->convert ? args->commit : NULL;
path += args->baselen;
- buffer = read_sha1_file(sha1, type, sizep);
+ buffer = read_object_file(oid, type, sizep);
if (buffer && S_ISREG(mode)) {
struct strbuf buf = STRBUF_INIT;
size_t size = 0;
return check && ATTR_TRUE(check->items[1].value);
}
-static int write_archive_entry(const unsigned char *sha1, const char *base,
+static int write_archive_entry(const struct object_id *oid, const char *base,
int baselen, const char *filename, unsigned mode, int stage,
void *context)
{
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
if (args->verbose)
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
- err = write_entry(args, sha1, path.buf, path.len, mode);
+ err = write_entry(args, oid, path.buf, path.len, mode);
if (err)
return err;
return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
if (args->verbose)
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
- return write_entry(args, sha1, path.buf, path.len, mode);
+ return write_entry(args, oid, path.buf, path.len, mode);
}
static void queue_directory(const unsigned char *sha1,
d->path[d->len - 1] = '\0'; /* no trailing slash */
ret =
write_directory(c) ||
- write_archive_entry(d->oid.hash, d->path, d->baselen,
+ write_archive_entry(&d->oid, d->path, d->baselen,
d->path + d->baselen, d->mode,
d->stage, c) != READ_TREE_RECURSIVE;
free(d);
return ret ? -1 : 0;
}
-static int queue_or_write_archive_entry(const unsigned char *sha1,
+static int queue_or_write_archive_entry(const struct object_id *oid,
struct strbuf *base, const char *filename,
unsigned mode, int stage, void *context)
{
if (check_attr_export_ignore(check))
return 0;
- queue_directory(sha1, base, filename,
+ queue_directory(oid->hash, base, filename,
mode, stage, c);
return READ_TREE_RECURSIVE;
}
if (write_directory(c))
return -1;
- return write_archive_entry(sha1, base->buf, base->len, filename, mode,
+ return write_archive_entry(oid, base->buf, base->len, filename, mode,
stage, context);
}
len--;
if (args->verbose)
fprintf(stderr, "%.*s\n", (int)len, args->base);
- err = write_entry(args, args->tree->object.oid.hash, args->base,
+ err = write_entry(args, &args->tree->object.oid, args->base,
len, 040777);
if (err)
return err;
return NULL;
}
-static int reject_entry(const unsigned char *sha1, struct strbuf *base,
+static int reject_entry(const struct object_id *oid, struct strbuf *base,
const char *filename, unsigned mode,
int stage, void *context)
{
unsigned int mode;
int err;
- err = get_tree_entry(tree->object.oid.hash, prefix,
- tree_oid.hash, &mode);
+ err = get_tree_entry(&tree->object.oid, prefix, &tree_oid,
+ &mode);
if (err || !S_ISDIR(mode))
die("current working directory is untracked");
extern void init_zip_archiver(void);
typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
- const unsigned char *sha1,
+ const struct object_id *oid,
const char *path, size_t pathlen,
unsigned int mode);
extern int write_archive(int argc, const char **argv, const char *prefix, const char *name_hint, int remote);
const char *archive_format_from_filename(const char *filename);
-extern void *sha1_file_to_archive(const struct archiver_args *args,
- const char *path, const unsigned char *sha1,
- unsigned int mode, enum object_type *type,
- unsigned long *sizep);
+extern void *object_file_to_archive(const struct archiver_args *args,
+ const char *path, const struct object_id *oid,
+ unsigned int mode, enum object_type *type,
+ unsigned long *sizep);
#endif /* ARCHIVE_H */
unsigned flags = commit->object.flags;
enum object_type type;
unsigned long size;
- char *buf = read_sha1_file(commit->object.oid.hash, &type, &size);
+ char *buf = read_object_file(&commit->object.oid, &type,
+ &size);
const char *subject_start;
int subject_len;
fprintf(stderr, "%3d", weight(p));
else
fprintf(stderr, "---");
- fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.oid.hash));
+ fprintf(stderr, " %.*s", 8, oid_to_hex(&commit->object.oid));
for (pp = commit->parents; pp; pp = pp->next)
fprintf(stderr, " %.*s", 8,
- sha1_to_hex(pp->item->object.oid.hash));
+ oid_to_hex(&pp->item->object.oid));
subject_len = find_commit_subject(buf, &subject_start);
if (subject_len)
struct object_id blob_oid;
unsigned mode;
- if (!get_tree_entry(commit_oid->hash, path, blob_oid.hash, &mode) &&
- sha1_object_info(blob_oid.hash, NULL) == OBJ_BLOB)
+ if (!get_tree_entry(commit_oid, path, &blob_oid, &mode) &&
+ oid_object_info(&blob_oid, NULL) == OBJ_BLOB)
return;
}
textconv_object(o->path, o->mode, &o->blob_oid, 1, &file->ptr, &file_size))
;
else
- file->ptr = read_sha1_file(o->blob_oid.hash, &type,
- &file_size);
+ file->ptr = read_object_file(&o->blob_oid, &type,
+ &file_size);
file->size = file_size;
if (!file->ptr)
{
if (!is_null_oid(&origin->blob_oid))
return 0;
- if (get_tree_entry(origin->commit->object.oid.hash,
- origin->path,
- origin->blob_oid.hash, &origin->mode))
+ if (get_tree_entry(&origin->commit->object.oid, origin->path, &origin->blob_oid, &origin->mode))
goto error_out;
- if (sha1_object_info(origin->blob_oid.hash, NULL) != OBJ_BLOB)
+ if (oid_object_info(&origin->blob_oid, NULL) != OBJ_BLOB)
goto error_out;
return 0;
error_out:
&sb->final_buf_size))
;
else
- sb->final_buf = read_sha1_file(o->blob_oid.hash, &type,
- &sb->final_buf_size);
+ sb->final_buf = read_object_file(&o->blob_oid, &type,
+ &sb->final_buf_size);
if (!sb->final_buf)
die(_("cannot read blob %s for path %s"),
discard_cache();
read_cache_from(index_path);
- if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL))
+ if (write_index_as_tree(&orig_tree, &the_index, index_path, 0, NULL))
return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
say(state, stdout, _("Using index info to reconstruct a base tree..."));
return error(_("Did you hand edit your patch?\n"
"It does not apply to blobs recorded in its index."));
- if (write_index_as_tree(their_tree.hash, &the_index, index_path, 0, NULL))
+ if (write_index_as_tree(&their_tree, &the_index, index_path, 0, NULL))
return error("could not write tree");
say(state, stdout, _("Falling back to patching base and 3-way merge..."));
if (run_hook_le(NULL, "pre-applypatch", NULL))
exit(1);
- if (write_cache_as_tree(tree.hash, 0, NULL))
+ if (write_cache_as_tree(&tree, 0, NULL))
die(_("git write-tree failed to write a tree"));
if (!get_oid_commit("HEAD", &parent)) {
*/
if (!state->rebasing) {
am_destroy(state);
- close_all_packs();
+ close_all_packs(the_repository->objects);
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
}
if (fast_forward_to(head_tree, head_tree, 1))
return -1;
- if (write_cache_as_tree(index.hash, 0, NULL))
+ if (write_cache_as_tree(&index, 0, NULL))
return -1;
index_tree = parse_tree_indirect(&index);
static int update_auto_abbrev(int auto_abbrev, struct blame_origin *suspect)
{
- const char *uniq = find_unique_abbrev(suspect->commit->object.oid.hash,
+ const char *uniq = find_unique_abbrev(&suspect->commit->object.oid,
auto_abbrev);
int len = strlen(uniq);
if (auto_abbrev < len)
if (get_oid(name, &oid))
return 0;
- return OBJ_NONE < sha1_object_info(oid.hash, NULL);
+ return OBJ_NONE < oid_object_info(&oid, NULL);
}
int cmd_blame(int argc, const char **argv, const char *prefix)
for (;;) {
switch (parse_options_step(&ctx, options, blame_opt_usage)) {
case PARSE_OPT_HELP:
+ case PARSE_OPT_ERROR:
exit(129);
case PARSE_OPT_DONE:
if (ctx.argv[0])
bname.buf,
(flags & REF_ISBROKEN) ? "broken"
: (flags & REF_ISSYMREF) ? target
- : find_unique_abbrev(oid.hash, DEFAULT_ABBREV));
+ : find_unique_abbrev(&oid, DEFAULT_ABBREV));
}
delete_branch_config(bname.buf);
{
enum object_type type;
- *buf = read_sha1_file(oid->hash, &type, size);
+ *buf = read_object_file(oid, &type, size);
if (!*buf)
return error(_("cannot read object %s '%s'"),
oid_to_hex(oid), path);
switch (opt) {
case 't':
oi.type_name = &sb;
- if (sha1_object_info_extended(oid.hash, &oi, flags) < 0)
+ if (oid_object_info_extended(&oid, &oi, flags) < 0)
die("git cat-file: could not get object info");
if (sb.len) {
printf("%s\n", sb.buf);
case 's':
oi.sizep = &size;
- if (sha1_object_info_extended(oid.hash, &oi, flags) < 0)
+ if (oid_object_info_extended(&oid, &oi, flags) < 0)
die("git cat-file: could not get object info");
printf("%lu\n", size);
return 0;
/* else fallthrough */
case 'p':
- type = sha1_object_info(oid.hash, NULL);
+ type = oid_object_info(&oid, NULL);
if (type < 0)
die("Not a valid object name %s", obj_name);
if (type == OBJ_BLOB)
return stream_blob_to_fd(1, &oid, NULL, 0);
- buf = read_sha1_file(oid.hash, &type, &size);
+ buf = read_object_file(&oid, &type, &size);
if (!buf)
die("Cannot read object %s", obj_name);
case 0:
if (type_from_string(exp_type) == OBJ_BLOB) {
struct object_id blob_oid;
- if (sha1_object_info(oid.hash, NULL) == OBJ_TAG) {
- char *buffer = read_sha1_file(oid.hash, &type, &size);
+ if (oid_object_info(&oid, NULL) == OBJ_TAG) {
+ char *buffer = read_object_file(&oid, &type,
+ &size);
const char *target;
if (!skip_prefix(buffer, "object ", &target) ||
get_oid_hex(target, &blob_oid))
} else
oidcpy(&blob_oid, &oid);
- if (sha1_object_info(blob_oid.hash, NULL) == OBJ_BLOB)
+ if (oid_object_info(&blob_oid, NULL) == OBJ_BLOB)
return stream_blob_to_fd(1, &blob_oid, NULL, 0);
/*
* we attempted to dereference a tag to a blob
* fall-back to the usual case.
*/
}
- buf = read_object_with_reference(oid.hash, exp_type, &size, NULL);
+ buf = read_object_with_reference(&oid, exp_type, &size, NULL);
break;
default:
enum object_type type;
if (!textconv_object(data->rest, 0100644, oid,
1, &contents, &size))
- contents = read_sha1_file(oid->hash, &type,
- &size);
+ contents = read_object_file(oid,
+ &type,
+ &size);
if (!contents)
die("could not convert '%s' %s",
oid_to_hex(oid), data->rest);
unsigned long size;
void *contents;
- contents = read_sha1_file(oid->hash, &type, &size);
+ contents = read_object_file(oid, &type, &size);
if (!contents)
die("object %s disappeared", oid_to_hex(oid));
if (type != data->type)
struct strbuf buf = STRBUF_INIT;
if (!data->skip_object_info &&
- sha1_object_info_extended(data->oid.hash, &data->info,
- OBJECT_INFO_LOOKUP_REPLACE) < 0) {
+ oid_object_info_extended(&data->oid, &data->info,
+ OBJECT_INFO_LOOKUP_REPLACE) < 0) {
printf("%s missing\n",
obj_name ? obj_name : oid_to_hex(&data->oid));
fflush(stdout);
}
-static int update_some(const unsigned char *sha1, struct strbuf *base,
+static int update_some(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *context)
{
int len;
len = base->len + strlen(pathname);
ce = xcalloc(1, cache_entry_size(len));
- hashcpy(ce->oid.hash, sha1);
+ oidcpy(&ce->oid, oid);
memcpy(ce->name, base->buf, base->len);
memcpy(ce->name + base->len, pathname, len - base->len);
ce->ce_flags = create_ce_flags(0) | CE_UPDATE;
pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);
if (print_sha1_ellipsis()) {
fprintf(stderr, "%s %s... %s\n", msg,
- find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV), sb.buf);
+ find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
} else {
fprintf(stderr, "%s %s %s\n", msg,
- find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV), sb.buf);
+ find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
}
strbuf_release(&sb);
}
static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
{
strbuf_addstr(sb, " ");
- strbuf_add_unique_abbrev(sb, commit->object.oid.hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV);
strbuf_addch(sb, ' ');
if (!parse_commit(commit))
pp_commit_easy(CMIT_FMT_ONELINE, commit, sb);
" git branch <new-branch-name> %s\n\n",
/* Give ngettext() the count */
lost),
- find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
+ find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
}
/*
#include "connected.h"
#include "packfile.h"
#include "list-objects-filter-options.h"
+#include "object-store.h"
/*
* Overall FIXMEs:
transport_disconnect(transport);
if (option_dissociate) {
- close_all_packs();
+ close_all_packs(the_repository->objects);
dissociate_from_references();
}
usage(commit_tree_usage);
if (get_oid_commit(argv[i], &oid))
die("Not a valid object name %s", argv[i]);
- assert_sha1_type(oid.hash, OBJ_COMMIT);
+ assert_oid_type(&oid, OBJ_COMMIT);
new_parent(lookup_commit(&oid), &parents);
continue;
}
#include "cache.h"
#include "config.h"
#include "dir.h"
+#include "repository.h"
#include "builtin.h"
#include "parse-options.h"
#include "quote.h"
#include "packfile.h"
+#include "object-store.h"
static unsigned long garbage;
static off_t size_garbage;
struct strbuf loose_buf = STRBUF_INIT;
struct strbuf pack_buf = STRBUF_INIT;
struct strbuf garbage_buf = STRBUF_INIT;
- if (!packed_git)
- prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
+
+ for (p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
if (open_pack_index(p))
static void append_suffix(int depth, const struct object_id *oid, struct strbuf *dst)
{
- strbuf_addf(dst, "-%d-g%s", depth, find_unique_abbrev(oid->hash, abbrev));
+ strbuf_addf(dst, "-%d-g%s", depth, find_unique_abbrev(oid, abbrev));
}
static void describe_commit(struct object_id *oid, struct strbuf *dst)
if (!match_cnt) {
struct object_id *cmit_oid = &cmit->object.oid;
if (always) {
- strbuf_add_unique_abbrev(dst, cmit_oid->hash, abbrev);
+ strbuf_add_unique_abbrev(dst, cmit_oid, abbrev);
if (suffix)
strbuf_addstr(dst, suffix);
return;
if (cmit)
describe_commit(&oid, &sb);
- else if (sha1_object_info(oid.hash, NULL) == OBJ_BLOB)
+ else if (oid_object_info(&oid, NULL) == OBJ_BLOB)
describe_blob(oid, &sb);
else
die(_("%s is neither a commit nor blob"), arg);
} else {
enum object_type type;
unsigned long size;
- data = read_sha1_file(oid->hash, &type, &size);
+ data = read_object_file(oid, &type, &size);
if (!data)
die(_("could not read object %s for symlink %s"),
oid_to_hex(oid), path);
object = (struct object *)lookup_blob(oid);
eaten = 0;
} else {
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf)
die ("Could not read blob %s", oid_to_hex(oid));
- if (check_sha1_signature(oid->hash, buf, size, type_name(type)) < 0)
+ if (check_object_signature(oid, buf, size, type_name(type)) < 0)
die("sha1 mismatch in blob %s", oid_to_hex(oid));
object = parse_object_buffer(oid, type, size, buf, &eaten);
}
return;
}
- buf = read_sha1_file(tag->object.oid.hash, &type, &size);
+ buf = read_object_file(&tag->object.oid, &type, &size);
if (!buf)
die ("Could not read tag %s", oid_to_hex(&tag->object.oid));
message = memmem(buf, size, "\n\n", 2);
if (last_idnum < mark)
last_idnum = mark;
- type = sha1_object_info(oid.hash, NULL);
+ type = oid_object_info(&oid, NULL);
if (type < 0)
die("object not found: %s", oid_to_hex(&oid));
struct branch *current_branch = branch_get(NULL);
const char *pretty_ref = prettify_refname(ref->name);
- type = sha1_object_info(ref->new_oid.hash, NULL);
+ type = oid_object_info(&ref->new_oid, NULL);
if (type < 0)
die(_("object %s not found"), oid_to_hex(&ref->new_oid));
if (in_merge_bases(current, updated)) {
struct strbuf quickref = STRBUF_INIT;
int r;
- strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&quickref, ¤t->object.oid, DEFAULT_ABBREV);
strbuf_addstr(&quickref, "..");
- strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
(recurse_submodules != RECURSE_SUBMODULES_ON))
check_for_new_submodule_commits(&ref->new_oid);
} else if (force || ref->force) {
struct strbuf quickref = STRBUF_INIT;
int r;
- strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&quickref, ¤t->object.oid, DEFAULT_ABBREV);
strbuf_addstr(&quickref, "...");
- strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
(recurse_submodules != RECURSE_SUBMODULES_ON))
check_for_new_submodule_commits(&ref->new_oid);
string_list_clear(&list, 0);
- close_all_packs();
+ close_all_packs(the_repository->objects);
argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
if (verbosity < 0)
struct strbuf tagbuf = STRBUF_INIT;
for (i = 0; i < origins.nr; i++) {
- unsigned char *sha1 = origins.items[i].util;
+ struct object_id *oid = origins.items[i].util;
enum object_type type;
unsigned long size, len;
- char *buf = read_sha1_file(sha1, &type, &size);
+ char *buf = read_object_file(oid, &type, &size);
struct strbuf sig = STRBUF_INIT;
if (!buf || type != OBJ_TAG)
#include "builtin.h"
#include "cache.h"
+#include "repository.h"
#include "config.h"
#include "commit.h"
#include "tree.h"
#include "streaming.h"
#include "decorate.h"
#include "packfile.h"
+#include "object-store.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
const char *ret;
if (obj->type == OBJ_NONE) {
- enum object_type type = sha1_object_info(obj->oid.hash, NULL);
+ enum object_type type = oid_object_info(&obj->oid, NULL);
if (type > 0)
object_as_type(obj, type, 0);
}
unsigned long size;
int eaten;
- if (read_loose_object(path, oid->hash, &type, &size, &contents) < 0)
+ if (read_loose_object(path, oid, &type, &size, &contents) < 0)
return NULL;
if (!contents && type != OBJ_BLOB)
for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
} else {
+ struct alternate_object_database *alt_odb_list;
+
fsck_object_dir(get_object_directory());
- prepare_alt_odb();
+ prepare_alt_odb(the_repository);
+ alt_odb_list = the_repository->objects->alt_odb_list;
for (alt = alt_odb_list; alt; alt = alt->next)
fsck_object_dir(alt->path);
uint32_t total = 0, count = 0;
struct progress *progress = NULL;
- prepare_packed_git();
-
if (show_progress) {
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p;
+ p = p->next) {
if (open_pack_index(p))
continue;
total += p->num_objects;
progress = start_progress(_("Checking objects"), total);
}
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p;
+ p = p->next) {
/* verify gives error messages itself */
if (verify_pack(p, fsck_obj_buffer,
progress, count))
*/
#include "builtin.h"
+#include "repository.h"
#include "config.h"
#include "tempfile.h"
#include "lockfile.h"
#include "argv-array.h"
#include "commit.h"
#include "packfile.h"
+#include "object-store.h"
#define FAILED_RUN "failed to run %s"
if (gc_auto_pack_limit <= 0)
return 0;
- prepare_packed_git();
- for (cnt = 0, p = packed_git; p; p = p->next) {
+ for (cnt = 0, p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
if (p->pack_keep)
return error(FAILED_RUN, rerere.argv[0]);
report_garbage = report_pack_garbage;
- reprepare_packed_git();
+ reprepare_packed_git(the_repository);
if (pack_garbage.nr > 0)
clean_pack_garbage();
#include "pathspec.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "object-store.h"
static char const * const grep_usage[] = {
N_("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"),
void *data;
grep_read_lock();
- data = read_sha1_file(oid->hash, type, size);
+ data = read_object_file(oid, type, size);
grep_read_unlock();
return data;
}
* object.
*/
grep_read_lock();
- add_to_alternates_memory(submodule.objectdir);
+ add_to_alternates_memory(submodule.objects->objectdir);
grep_read_unlock();
if (oid) {
object = parse_object_or_die(oid, oid_to_hex(oid));
grep_read_lock();
- data = read_object_with_reference(object->oid.hash, tree_type,
+ data = read_object_with_reference(&object->oid, tree_type,
&size, NULL);
grep_read_unlock();
int hit, len;
grep_read_lock();
- data = read_object_with_reference(obj->oid.hash, tree_type,
+ data = read_object_with_reference(&obj->oid, tree_type,
&size, NULL);
grep_read_unlock();
#include "streaming.h"
#include "thread-utils.h"
#include "packfile.h"
+#include "object-store.h"
static const char index_pack_usage[] =
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
};
struct ref_delta_entry {
- unsigned char sha1[20];
+ struct object_id oid;
int obj_no;
};
if (!(obj->flags & FLAG_CHECKED)) {
unsigned long size;
- int type = sha1_object_info(obj->oid.hash, &size);
+ int type = oid_object_info(&obj->oid, &size);
if (type <= 0)
die(_("did not receive expected object %s"),
oid_to_hex(&obj->oid));
*last_index = last;
}
-static int compare_ref_delta_bases(const unsigned char *sha1,
- const unsigned char *sha2,
+static int compare_ref_delta_bases(const struct object_id *oid1,
+ const struct object_id *oid2,
enum object_type type1,
enum object_type type2)
{
int cmp = type1 - type2;
if (cmp)
return cmp;
- return hashcmp(sha1, sha2);
+ return oidcmp(oid1, oid2);
}
-static int find_ref_delta(const unsigned char *sha1, enum object_type type)
+static int find_ref_delta(const struct object_id *oid, enum object_type type)
{
int first = 0, last = nr_ref_deltas;
struct ref_delta_entry *delta = &ref_deltas[next];
int cmp;
- cmp = compare_ref_delta_bases(sha1, delta->sha1,
+ cmp = compare_ref_delta_bases(oid, &delta->oid,
type, objects[delta->obj_no].type);
if (!cmp)
return next;
return -first-1;
}
-static void find_ref_delta_children(const unsigned char *sha1,
+static void find_ref_delta_children(const struct object_id *oid,
int *first_index, int *last_index,
enum object_type type)
{
- int first = find_ref_delta(sha1, type);
+ int first = find_ref_delta(oid, type);
int last = first;
int end = nr_ref_deltas - 1;
*last_index = -1;
return;
}
- while (first > 0 && !hashcmp(ref_deltas[first - 1].sha1, sha1))
+ while (first > 0 && !oidcmp(&ref_deltas[first - 1].oid, oid))
--first;
- while (last < end && !hashcmp(ref_deltas[last + 1].sha1, sha1))
+ while (last < end && !oidcmp(&ref_deltas[last + 1].oid, oid))
++last;
*first_index = first;
*last_index = last;
memset(&data, 0, sizeof(data));
data.entry = entry;
- data.st = open_istream(entry->idx.oid.hash, &type, &size, NULL);
+ data.st = open_istream(&entry->idx.oid, &type, &size, NULL);
if (!data.st)
return -1;
if (size != entry->size || type != entry->type)
enum object_type has_type;
unsigned long has_size;
read_lock();
- has_type = sha1_object_info(oid->hash, &has_size);
+ has_type = oid_object_info(oid, &has_size);
if (has_type < 0)
die(_("cannot read existing object info %s"), oid_to_hex(oid));
if (has_type != type || has_size != size)
die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid));
- has_data = read_sha1_file(oid->hash, &has_type, &has_size);
+ has_data = read_object_file(oid, &has_type, &has_size);
read_unlock();
if (!data)
data = new_data = get_data_from_pack(obj_entry);
struct base_data *prev_base)
{
if (base->ref_last == -1 && base->ofs_last == -1) {
- find_ref_delta_children(base->obj->idx.oid.hash,
+ find_ref_delta_children(&base->obj->idx.oid,
&base->ref_first, &base->ref_last,
OBJ_REF_DELTA);
const struct ref_delta_entry *delta_a = a;
const struct ref_delta_entry *delta_b = b;
- return hashcmp(delta_a->sha1, delta_b->sha1);
+ return oidcmp(&delta_a->oid, &delta_b->oid);
}
static void resolve_base(struct object_entry *obj)
ofs_delta++;
} else if (obj->type == OBJ_REF_DELTA) {
ALLOC_GROW(ref_deltas, nr_ref_deltas + 1, ref_deltas_alloc);
- hashcpy(ref_deltas[nr_ref_deltas].sha1, ref_delta_oid.hash);
+ oidcpy(&ref_deltas[nr_ref_deltas].oid, &ref_delta_oid);
ref_deltas[nr_ref_deltas].obj_no = i;
nr_ref_deltas++;
} else if (!data) {
if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
continue;
- base_obj->data = read_sha1_file(d->sha1, &type, &base_obj->size);
+ base_obj->data = read_object_file(&d->oid, &type,
+ &base_obj->size);
if (!base_obj->data)
continue;
- if (check_sha1_signature(d->sha1, base_obj->data,
+ if (check_object_signature(&d->oid, base_obj->data,
base_obj->size, type_name(type)))
- die(_("local object %s is corrupt"), sha1_to_hex(d->sha1));
- base_obj->obj = append_obj_to_pack(f, d->sha1,
+ die(_("local object %s is corrupt"), oid_to_hex(&d->oid));
+ base_obj->obj = append_obj_to_pack(f, d->oid.hash,
base_obj->data, base_obj->size, type);
find_unresolved_deltas(base_obj);
display_progress(progress, nr_resolved_deltas);
{
unsigned long size;
enum object_type type;
- char *buf = read_sha1_file(oid->hash, &type, &size);
+ char *buf = read_object_file(oid, &type, &size);
int offset = 0;
if (!buf)
return 0;
}
-static int show_tree_object(const unsigned char *sha1,
+static int show_tree_object(const struct object_id *oid,
struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *context)
{
{
if (!verbose) {
fprintf(file, "%c %s\n", sign,
- find_unique_abbrev(commit->object.oid.hash, abbrev));
+ find_unique_abbrev(&commit->object.oid, abbrev));
} else {
struct strbuf buf = STRBUF_INIT;
pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
fprintf(file, "%c %s %s\n", sign,
- find_unique_abbrev(commit->object.oid.hash, abbrev),
+ find_unique_abbrev(&commit->object.oid, abbrev),
buf.buf);
strbuf_release(&buf);
}
printf("%s%06o %s %d\t",
tag,
ce->ce_mode,
- find_unique_abbrev(ce->oid.hash, abbrev),
+ find_unique_abbrev(&ce->oid, abbrev),
ce_stage(ce));
}
write_eolinfo(repo->index, ce, fullname);
if (!ui->mode[i])
continue;
printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
- find_unique_abbrev(ui->sha1[i], abbrev),
+ find_unique_abbrev(&ui->oid[i], abbrev),
i + 1);
write_name(path);
}
return 0;
}
-static int show_tree(const unsigned char *sha1, struct strbuf *base,
+static int show_tree(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *context)
{
int retval = 0;
char size_text[24];
if (!strcmp(type, blob_type)) {
unsigned long size;
- if (sha1_object_info(sha1, &size) == OBJ_BAD)
+ if (oid_object_info(oid, &size) == OBJ_BAD)
xsnprintf(size_text, sizeof(size_text),
"BAD");
else
} else
xsnprintf(size_text, sizeof(size_text), "-");
printf("%06o %s %s %7s\t", mode, type,
- find_unique_abbrev(sha1, abbrev),
+ find_unique_abbrev(oid, abbrev),
size_text);
} else
printf("%06o %s %s\t", mode, type,
- find_unique_abbrev(sha1, abbrev));
+ find_unique_abbrev(oid, abbrev));
}
baselen = base->len;
strbuf_addstr(base, pathname);
const char *path = entry->path;
if (!entry->stage)
- return read_sha1_file(entry->blob->object.oid.hash, &type, size);
+ return read_object_file(&entry->blob->object.oid, &type, size);
base = NULL;
if (entry->stage == 1) {
base = entry->blob;
enum object_type type;
while (entry) {
if (entry->stage == 2)
- return read_sha1_file(entry->blob->object.oid.hash, &type, size);
+ return read_object_file(&entry->blob->object.oid,
+ &type, size);
entry = entry->link;
}
return NULL;
* We ignore errors in 'gc --auto', since the
* user should see them.
*/
- close_all_packs();
+ close_all_packs(the_repository->objects);
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
}
static void write_tree_trivial(struct object_id *oid)
{
- if (write_cache_as_tree(oid->hash, 0, NULL))
+ if (write_cache_as_tree(oid, 0, NULL))
die(_("git write-tree failed to write a tree"));
}
check_commit_signature(commit, &signature_check);
- find_unique_abbrev_r(hex, commit->object.oid.hash, DEFAULT_ABBREV);
+ find_unique_abbrev_r(hex, &commit->object.oid, DEFAULT_ABBREV);
switch (signature_check.result) {
case 'G':
break;
if (verbosity >= 0) {
printf(_("Updating %s..%s\n"),
- find_unique_abbrev(head_commit->object.oid.hash,
+ find_unique_abbrev(&head_commit->object.oid,
DEFAULT_ABBREV),
- find_unique_abbrev(remoteheads->item->object.oid.hash,
+ find_unique_abbrev(&remoteheads->item->object.oid,
DEFAULT_ABBREV));
}
strbuf_addstr(&msg, "Fast-forward");
/*
* We refuse to tag something we can't verify. Just because.
*/
-static int verify_object(const unsigned char *sha1, const char *expected_type)
+static int verify_object(const struct object_id *oid, const char *expected_type)
{
int ret = -1;
enum object_type type;
unsigned long size;
- void *buffer = read_sha1_file(sha1, &type, &size);
- const unsigned char *repl = lookup_replace_object(sha1);
+ void *buffer = read_object_file(oid, &type, &size);
+ const struct object_id *repl = lookup_replace_object(oid);
if (buffer) {
if (type == type_from_string(expected_type))
- ret = check_sha1_signature(repl, buffer, size, expected_type);
+ ret = check_object_signature(repl, buffer, size, expected_type);
free(buffer);
}
return ret;
{
int typelen;
char type[20];
- unsigned char sha1[20];
- const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb;
+ struct object_id oid;
+ const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
size_t len;
if (size < 84)
if (memcmp(object, "object ", 7))
return error("char%d: does not start with \"object \"", 0);
- if (get_sha1_hex(object + 7, sha1))
+ if (parse_oid_hex(object + 7, &oid, &p))
return error("char%d: could not get SHA1 hash", 7);
/* Verify type line */
- type_line = object + 48;
+ type_line = p + 1;
if (memcmp(type_line - 1, "\ntype ", 6))
return error("char%d: could not find \"\\ntype \"", 47);
type[typelen] = 0;
/* Verify that the object matches */
- if (verify_object(sha1, type))
- return error("char%d: could not verify object %s", 7, sha1_to_hex(sha1));
+ if (verify_object(&oid, type))
+ return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
/* Verify the tag-name: we don't allow control characters or spaces in it */
tag_line += 4;
static struct treeent {
unsigned mode;
- unsigned char sha1[20];
+ struct object_id oid;
int len;
char name[FLEX_ARRAY];
} **entries;
static int alloc, used;
-static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
+static void append_to_tree(unsigned mode, struct object_id *oid, char *path)
{
struct treeent *ent;
size_t len = strlen(path);
FLEX_ALLOC_MEM(ent, name, path, len);
ent->mode = mode;
ent->len = len;
- hashcpy(ent->sha1, sha1);
+ oidcpy(&ent->oid, oid);
ALLOC_GROW(entries, used + 1, alloc);
entries[used++] = ent;
for (i = 0; i < used; i++) {
struct treeent *ent = entries[i];
strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
- strbuf_add(&buf, ent->sha1, 20);
+ strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);
}
write_object_file(buf.buf, buf.len, tree_type, oid);
static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_missing)
{
char *ptr, *ntr;
+ const char *p;
unsigned mode;
enum object_type mode_type; /* object type derived from mode */
enum object_type obj_type; /* object type derived from sha */
char *path, *to_free = NULL;
- unsigned char sha1[20];
+ struct object_id oid;
ptr = buf;
/*
die("input format error: %s", buf);
ptr = ntr + 1; /* type */
ntr = strchr(ptr, ' ');
- if (!ntr || buf + len <= ntr + 40 ||
- ntr[41] != '\t' ||
- get_sha1_hex(ntr + 1, sha1))
+ if (!ntr || parse_oid_hex(ntr + 1, &oid, &p) ||
+ *p != '\t')
die("input format error: %s", buf);
/* It is perfectly normal if we do not have a commit from a submodule */
}
/* Check the type of object identified by sha1 */
- obj_type = sha1_object_info(sha1, NULL);
+ obj_type = oid_object_info(&oid, NULL);
if (obj_type < 0) {
if (allow_missing) {
; /* no problem - missing objects are presumed to be of the right type */
} else {
- die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1));
+ die("entry '%s' object %s is unavailable", path, oid_to_hex(&oid));
}
} else {
if (obj_type != mode_type) {
* because the new tree entry will never be correct.
*/
die("entry '%s' object %s is a %s but specified type was (%s)",
- path, sha1_to_hex(sha1), type_name(obj_type), type_name(mode_type));
+ path, oid_to_hex(&oid), type_name(obj_type), type_name(mode_type));
}
}
- append_to_tree(mode, sha1, path);
+ append_to_tree(mode, &oid, path);
free(to_free);
}
else if (allow_undefined)
printf("undefined\n");
else if (always)
- printf("%s\n", find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
+ printf("%s\n", find_unique_abbrev(oid, DEFAULT_ABBREV));
else
die("cannot describe '%s'", oid_to_hex(oid));
strbuf_release(&buf);
return 0;
}
-static void copy_obj_to_fd(int fd, const unsigned char *sha1)
+static void copy_obj_to_fd(int fd, const struct object_id *oid)
{
unsigned long size;
enum object_type type;
- char *buf = read_sha1_file(sha1, &type, &size);
+ char *buf = read_object_file(oid, &type, &size);
if (buf) {
if (size)
write_or_die(fd, buf, size);
}
static void prepare_note_data(const struct object_id *object, struct note_data *d,
- const unsigned char *old_note)
+ const struct object_id *old_note)
{
if (d->use_editor || !d->given) {
int fd;
if (get_oid(arg, &object))
die(_("failed to resolve '%s' as a valid ref."), arg);
- if (!(buf = read_sha1_file(object.hash, &type, &len))) {
+ if (!(buf = read_object_file(&object, &type, &len))) {
free(buf);
die(_("failed to read object '%s'."), arg);
}
oid_to_hex(&object));
}
- prepare_note_data(&object, &d, note ? note->hash : NULL);
+ prepare_note_data(&object, &d, note);
if (d.buf.len || allow_empty) {
write_note_data(&d, &new_note);
if (add_note(t, &object, &new_note, combine_notes_overwrite))
t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
note = get_note(t, &object);
- prepare_note_data(&object, &d, edit && note ? note->hash : NULL);
+ prepare_note_data(&object, &d, edit && note ? note : NULL);
if (note && !edit) {
/* Append buf to previous note contents */
unsigned long size;
enum object_type type;
- char *prev_buf = read_sha1_file(note->hash, &type, &size);
+ char *prev_buf = read_object_file(note, &type, &size);
strbuf_grow(&d.buf, size + 1);
if (d.buf.len && prev_buf && size)
#include "builtin.h"
#include "cache.h"
+#include "repository.h"
#include "config.h"
#include "attr.h"
#include "object.h"
#include "argv-array.h"
#include "list.h"
#include "packfile.h"
+#include "object-store.h"
static const char *pack_usage[] = {
N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"),
void *buf, *base_buf, *delta_buf;
enum object_type type;
- buf = read_sha1_file(entry->idx.oid.hash, &type, &size);
+ buf = read_object_file(&entry->idx.oid, &type, &size);
if (!buf)
die("unable to read %s", oid_to_hex(&entry->idx.oid));
- base_buf = read_sha1_file(entry->delta->idx.oid.hash, &type,
- &base_size);
+ base_buf = read_object_file(&entry->delta->idx.oid, &type, &base_size);
if (!base_buf)
die("unable to read %s",
oid_to_hex(&entry->delta->idx.oid));
if (!usable_delta) {
if (entry->type == OBJ_BLOB &&
entry->size > big_file_threshold &&
- (st = open_istream(entry->idx.oid.hash, &type, &size, NULL)) != NULL)
+ (st = open_istream(&entry->idx.oid, &type, &size, NULL)) != NULL)
buf = NULL;
else {
- buf = read_sha1_file(entry->idx.oid.hash, &type,
- &size);
+ buf = read_object_file(&entry->idx.oid, &type, &size);
if (!buf)
die(_("unable to read %s"),
oid_to_hex(&entry->idx.oid));
if (want != -1)
return want;
}
-
- list_for_each(pos, &packed_git_mru) {
+ list_for_each(pos, get_packed_git_mru(the_repository)) {
struct packed_git *p = list_entry(pos, struct packed_git, mru);
off_t offset;
}
want = want_found_object(exclude, p);
if (!exclude && want > 0)
- list_move(&p->mru, &packed_git_mru);
+ list_move(&p->mru,
+ get_packed_git_mru(the_repository));
if (want != -1)
return want;
}
/* Did not find one. Either we got a bogus request or
* we need to read and perhaps cache.
*/
- data = read_sha1_file(oid->hash, &type, &size);
+ data = read_object_file(oid, &type, &size);
if (!data)
return NULL;
if (type != OBJ_TREE) {
if (window <= num_preferred_base++)
return;
- data = read_object_with_reference(oid->hash, tree_type, &size, tree_oid.hash);
+ data = read_object_with_reference(oid, tree_type, &size, &tree_oid);
if (!data)
return;
unuse_pack(&w_curs);
}
- entry->type = sha1_object_info(entry->idx.oid.hash, &entry->size);
+ entry->type = oid_object_info(&entry->idx.oid, &entry->size);
/*
* The error condition is checked in prepare_pack(). This is
* to permit a missing preferred base object to be ignored
* And if that fails, the error will be recorded in entry->type
* and dealt with in prepare_pack().
*/
- entry->type = sha1_object_info(entry->idx.oid.hash,
- &entry->size);
+ entry->type = oid_object_info(&entry->idx.oid, &entry->size);
}
}
/* Load data if not already done */
if (!trg->data) {
read_lock();
- trg->data = read_sha1_file(trg_entry->idx.oid.hash, &type,
- &sz);
+ trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz);
read_unlock();
if (!trg->data)
die("object %s cannot be read",
}
if (!src->data) {
read_lock();
- src->data = read_sha1_file(src_entry->idx.oid.hash, &type,
- &sz);
+ src->data = read_object_file(&src_entry->idx.oid, &type, &sz);
read_unlock();
if (!src->data) {
if (src_entry->preferred_base) {
memset(&in_pack, 0, sizeof(in_pack));
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p; p = p->next) {
struct object_id oid;
struct object *o;
static int add_loose_object(const struct object_id *oid, const char *path,
void *data)
{
- enum object_type type = sha1_object_info(oid->hash, NULL);
+ enum object_type type = oid_object_info(oid, NULL);
if (type < 0) {
warning("loose object at %s could not be examined", path);
static struct packed_git *last_found = (void *)1;
struct packed_git *p;
- p = (last_found != (void *)1) ? last_found : packed_git;
+ p = (last_found != (void *)1) ? last_found :
+ get_packed_git(the_repository);
while (p) {
if ((!p->pack_local || p->pack_keep) &&
return 1;
}
if (p == last_found)
- p = packed_git;
+ p = get_packed_git(the_repository);
else
p = p->next;
if (p == last_found)
uint32_t i;
struct object_id oid;
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local || p->pack_keep)
continue;
if (progress && all_progress_implied)
progress = 2;
- prepare_packed_git();
if (ignore_packed_keep) {
struct packed_git *p;
- for (p = packed_git; p; p = p->next)
+ for (p = get_packed_git(the_repository); p; p = p->next)
if (p->pack_local && p->pack_keep)
break;
if (!p) /* no keep-able packs found */
* also covers non-local objects
*/
struct packed_git *p;
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local) {
have_non_local_packs = 1;
break;
*/
#include "builtin.h"
+#include "repository.h"
#include "packfile.h"
+#include "object-store.h"
#define BLKSIZE 512
static struct pack_list * add_pack_file(const char *filename)
{
- struct packed_git *p = packed_git;
+ struct packed_git *p = get_packed_git(the_repository);
if (strlen(filename) < 40)
die("Bad pack filename: %s", filename);
static void load_all(void)
{
- struct packed_git *p = packed_git;
+ struct packed_git *p = get_packed_git(the_repository);
while (p) {
add_pack(p);
break;
}
- prepare_packed_git();
-
if (load_all_packs)
load_all();
else
if (st.st_mtime > expire)
return 0;
if (show_only || verbose) {
- enum object_type type = sha1_object_info(oid->hash, NULL);
+ enum object_type type = oid_object_info(oid, NULL);
printf("%s %s\n", oid_to_hex(oid),
(type > 0) ? type_name(type) : "unknown");
}
#include "builtin.h"
+#include "repository.h"
#include "config.h"
#include "lockfile.h"
#include "pack.h"
rp_error("refusing inconsistent update between symref '%s' (%s..%s) and"
" its target '%s' (%s..%s)",
cmd->ref_name,
- find_unique_abbrev(cmd->old_oid.hash, DEFAULT_ABBREV),
- find_unique_abbrev(cmd->new_oid.hash, DEFAULT_ABBREV),
+ find_unique_abbrev(&cmd->old_oid, DEFAULT_ABBREV),
+ find_unique_abbrev(&cmd->new_oid, DEFAULT_ABBREV),
dst_cmd->ref_name,
- find_unique_abbrev(dst_cmd->old_oid.hash, DEFAULT_ABBREV),
- find_unique_abbrev(dst_cmd->new_oid.hash, DEFAULT_ABBREV));
+ find_unique_abbrev(&dst_cmd->old_oid, DEFAULT_ABBREV),
+ find_unique_abbrev(&dst_cmd->new_oid, DEFAULT_ABBREV));
cmd->error_string = dst_cmd->error_string =
"inconsistent aliased update";
status = finish_command(&child);
if (status)
return "index-pack abnormal exit";
- reprepare_packed_git();
+ reprepare_packed_git(the_repository);
}
return NULL;
}
proc.git_cmd = 1;
proc.argv = argv_gc_auto;
- close_all_packs();
+ close_all_packs(the_repository->objects);
if (!start_command(&proc)) {
if (use_sideband)
copy_to_sideband(proc.err, -1, NULL);
if (!tree->buffer) {
enum object_type type;
unsigned long size;
- void *data = read_sha1_file(oid->hash, &type, &size);
+ void *data = read_object_file(oid, &type, &size);
if (!data) {
tree->object.flags |= INCOMPLETE;
return 0;
if (get_oid(refname, &object))
return error("Failed to resolve '%s' as a valid ref.", refname);
- obj_type = sha1_object_info(object.hash, NULL);
- repl_type = sha1_object_info(oid->hash, NULL);
+ obj_type = oid_object_info(&object, NULL);
+ repl_type = oid_object_info(oid, NULL);
printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type),
oid_to_hex(oid), type_name(repl_type));
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
- obj_type = sha1_object_info(object->hash, NULL);
- repl_type = sha1_object_info(repl->hash, NULL);
+ obj_type = oid_object_info(object, NULL);
+ repl_type = oid_object_info(repl, NULL);
if (!force && obj_type != repl_type)
die("Objects must be of the same type.\n"
"'%s' points to a replaced object of type '%s'\n"
if (get_oid(object_ref, &old_oid) < 0)
die("Not a valid object name: '%s'", object_ref);
- type = sha1_object_info(old_oid.hash, NULL);
+ type = oid_object_info(&old_oid, NULL);
if (type < 0)
die("unable to get object type for %s", oid_to_hex(&old_oid));
struct strbuf buf = STRBUF_INIT;
printf(_("HEAD is now at %s"),
- find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
+ find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
if (buf.len > 0)
if (!revs->graph)
fputs(get_revision_mark(revs, commit), stdout);
if (revs->abbrev_commit && revs->abbrev)
- fputs(find_unique_abbrev(commit->object.oid.hash, revs->abbrev),
+ fputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),
stdout);
else
fputs(oid_to_hex(&commit->object.oid), stdout);
}
}
else if (abbrev)
- show_with_type(type, find_unique_abbrev(oid->hash, abbrev));
+ show_with_type(type, find_unique_abbrev(oid, abbrev));
else
show_with_type(type, oid_to_hex(oid));
}
* way as changed from the HEAD.
*/
if (no_head
- || get_tree_entry(head->hash, name, oid.hash, &mode)
+ || get_tree_entry(head, name, &oid, &mode)
|| ce->ce_mode != create_ce_mode(mode)
|| oidcmp(&ce->oid, &oid))
staged_changes = 1;
#include "parse-options.h"
static char const * const shortlog_usage[] = {
- N_("git shortlog [<options>] [<revision-range>] [[--] [<path>...]]"),
+ N_("git shortlog [<options>] [<revision-range>] [[--] <path>...]"),
+ N_("git log --pretty=short | git shortlog [<options>]"),
NULL
};
for (;;) {
switch (parse_options_step(&ctx, options, shortlog_usage)) {
case PARSE_OPT_HELP:
+ case PARSE_OPT_ERROR:
exit(129);
case PARSE_OPT_DONE:
goto parse_done;
parse_done:
argc = parse_options_end(&ctx);
+ if (nongit && argc > 1) {
+ error(_("too many arguments given outside repository"));
+ usage_with_options(shortlog_usage, options);
+ }
+
if (setup_revisions(argc, argv, &rev, NULL) != 1) {
error(_("unrecognized argument: %s"), argv[1]);
usage_with_options(shortlog_usage, options);
}
else
printf("[%s] ",
- find_unique_abbrev(commit->object.oid.hash,
+ find_unique_abbrev(&commit->object.oid,
DEFAULT_ABBREV));
}
puts(pretty_str);
if (quiet)
return;
- hex = find_unique_abbrev(oid->hash, abbrev);
+ hex = find_unique_abbrev(oid, abbrev);
if (hash_only)
printf("%s\n", hex);
else
return;
if (!peel_ref(refname, &peeled)) {
- hex = find_unique_abbrev(peeled.hash, abbrev);
+ hex = find_unique_abbrev(&peeled, abbrev);
printf("%s %s^{}\n", hex, refname);
}
}
#include "revision.h"
#include "diffcore.h"
#include "diff.h"
+#include "object-store.h"
#define OPT_QUIET (1 << 0)
#define OPT_CACHED (1 << 1)
displaypath);
} else if (!(flags & OPT_CACHED)) {
struct object_id oid;
+ struct ref_store *refs = get_submodule_ref_store(path);
- if (refs_head_ref(get_submodule_ref_store(path),
- handle_submodule_head_ref, &oid))
+ if (!refs) {
+ print_status(flags, '-', path, ce_oid, displaypath);
+ goto cleanup;
+ }
+ if (refs_head_ref(refs, handle_submodule_head_ref, &oid))
die(_("could not resolve HEAD ref inside the "
"submodule '%s'"), path);
{
if (delete_ref(NULL, ref, oid, 0))
return 1;
- printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
+ printf(_("Deleted tag '%s' (was %s)\n"), name,
+ find_unique_abbrev(oid, DEFAULT_ABBREV));
return 0;
}
enum object_type type;
char *buf, *sp;
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf)
return;
/* skip header */
struct strbuf header = STRBUF_INIT;
char *path = NULL;
- type = sha1_object_info(object->hash, NULL);
+ type = oid_object_info(object, NULL);
if (type <= OBJ_NONE)
die(_("bad object type."));
strbuf_addstr(sb, rla);
} else {
strbuf_addstr(sb, "tag: tagging ");
- strbuf_add_unique_abbrev(sb, oid->hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(sb, oid, DEFAULT_ABBREV);
}
strbuf_addstr(sb, " (");
- type = sha1_object_info(oid->hash, NULL);
+ type = oid_object_info(oid, NULL);
switch (type) {
default:
strbuf_addstr(sb, "object of unknown type");
break;
case OBJ_COMMIT:
- if ((buf = read_sha1_file(oid->hash, &type, &size)) != NULL) {
+ if ((buf = read_object_file(oid, &type, &size)) != NULL) {
subject_len = find_commit_subject(buf, &subject_start);
strbuf_insert(sb, sb->len, subject_start, subject_len);
} else {
die("%s", err.buf);
ref_transaction_free(transaction);
if (force && !is_null_oid(&prev) && oidcmp(&prev, &object))
- printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev.hash, DEFAULT_ABBREV));
+ printf(_("Updated tag '%s' (was %s)\n"), tag,
+ find_unique_abbrev(&prev, DEFAULT_ABBREV));
UNLEAK(buf);
UNLEAK(ref);
unsigned long size;
int fd;
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf || type != OBJ_BLOB)
die("unable to read blob object %s", oid_to_hex(oid));
if (!(obj->flags & FLAG_OPEN)) {
unsigned long size;
- int type = sha1_object_info(obj->oid.hash, &size);
+ int type = oid_object_info(&obj->oid, &size);
if (type != obj->type || type <= 0)
die("object of unexpected type");
obj->flags |= FLAG_WRITTEN;
if (resolve_against_held(nr, &base_oid, delta_data, delta_size))
return;
- base = read_sha1_file(base_oid.hash, &type, &base_size);
+ base = read_object_file(&base_oid, &type, &base_size);
if (!base) {
error("failed to read delta-pack base object %s",
oid_to_hex(&base_oid));
int size;
struct cache_entry *ce;
- if (get_tree_entry(ent->hash, path, oid.hash, &mode)) {
+ if (get_tree_entry(ent, path, &oid, &mode)) {
if (which)
error("%s: not in %s branch.", path, which);
return NULL;
break;
switch (parseopt_state) {
case PARSE_OPT_HELP:
+ case PARSE_OPT_ERROR:
exit(129);
case PARSE_OPT_NON_OPTION:
case PARSE_OPT_DONE:
if (get_oid(name, &oid))
return error("commit '%s' not found.", name);
- buf = read_sha1_file(oid.hash, &type, &size);
+ buf = read_object_file(&oid, &type, &size);
if (!buf)
return error("%s: unable to read file.", name);
if (type != OBJ_COMMIT)
}
path[len] = '\0';
if (!file_exists(path)) {
- struct stat st_link;
free(path);
- /*
- * the repo is moved manually and has not been
- * accessed since?
- */
- if (!stat(git_path("worktrees/%s/link", id), &st_link) &&
- st_link.st_nlink > 1)
- return 0;
- if (st.st_mtime <= expire) {
+ if (stat(git_path("worktrees/%s/index", id), &st) ||
+ st.st_mtime <= expire) {
strbuf_addf(reason, _("Removing worktrees/%s: gitdir file points to non-existent location"), id);
return 1;
} else {
strbuf_addstr(&sb, "(bare)");
else {
strbuf_addf(&sb, "%-*s ", abbrev_len,
- find_unique_abbrev(wt->head_oid.hash, DEFAULT_ABBREV));
+ find_unique_abbrev(&wt->head_oid, DEFAULT_ABBREV));
if (wt->is_detached)
strbuf_addstr(&sb, "(detached HEAD)");
else if (wt->head_ref) {
if (path_len > *maxlen)
*maxlen = path_len;
- sha1_len = strlen(find_unique_abbrev(wt[i]->head_oid.hash, *abbrev));
+ sha1_len = strlen(find_unique_abbrev(&wt[i]->head_oid, *abbrev));
if (sha1_len > *abbrev)
*abbrev = sha1_len;
}
{
int flags = 0, ret;
const char *prefix = NULL;
- unsigned char sha1[20];
+ struct object_id oid;
const char *me = "git-write-tree";
struct option write_tree_options[] = {
OPT_BIT(0, "missing-ok", &flags, N_("allow missing objects"),
argc = parse_options(argc, argv, unused_prefix, write_tree_options,
write_tree_usage, 0);
- ret = write_cache_as_tree(sha1, flags, prefix);
+ ret = write_cache_as_tree(&oid, flags, prefix);
switch (ret) {
case 0:
- printf("%s\n", sha1_to_hex(sha1));
+ printf("%s\n", oid_to_hex(&oid));
break;
case WRITE_TREE_UNREADABLE_INDEX:
die("%s: error reading the index", me);
*/
#include "cache.h"
#include "bulk-checkin.h"
+#include "repository.h"
#include "csum-file.h"
#include "pack.h"
#include "strbuf.h"
strbuf_release(&packname);
/* Make objects we just wrote available to ourselves */
- reprepare_packed_git();
+ reprepare_packed_git(the_repository);
}
-static int already_written(struct bulk_checkin_state *state, unsigned char sha1[])
+static int already_written(struct bulk_checkin_state *state, struct object_id *oid)
{
int i;
/* The object may already exist in the repository */
- if (has_sha1_file(sha1))
+ if (has_sha1_file(oid->hash))
return 1;
/* Might want to keep the list sorted */
for (i = 0; i < state->nr_written; i++)
- if (!hashcmp(state->written[i]->oid.hash, sha1))
+ if (!oidcmp(&state->written[i]->oid, oid))
return 1;
/* This is a new object we need to keep */
}
static int deflate_to_pack(struct bulk_checkin_state *state,
- unsigned char result_sha1[],
+ struct object_id *result_oid,
int fd, size_t size,
enum object_type type, const char *path,
unsigned flags)
if (lseek(fd, seekback, SEEK_SET) == (off_t) -1)
return error("cannot seek back");
}
- the_hash_algo->final_fn(result_sha1, &ctx);
+ the_hash_algo->final_fn(result_oid->hash, &ctx);
if (!idx)
return 0;
idx->crc32 = crc32_end(state->f);
- if (already_written(state, result_sha1)) {
+ if (already_written(state, result_oid)) {
hashfile_truncate(state->f, &checkpoint);
state->offset = checkpoint.offset;
free(idx);
} else {
- hashcpy(idx->oid.hash, result_sha1);
+ oidcpy(&idx->oid, result_oid);
ALLOC_GROW(state->written,
state->nr_written + 1,
state->alloc_written);
return 0;
}
-int index_bulk_checkin(unsigned char *sha1,
+int index_bulk_checkin(struct object_id *oid,
int fd, size_t size, enum object_type type,
const char *path, unsigned flags)
{
- int status = deflate_to_pack(&state, sha1, fd, size, type,
+ int status = deflate_to_pack(&state, oid, fd, size, type,
path, flags);
if (!state.plugged)
finish_bulk_checkin(&state);
#ifndef BULK_CHECKIN_H
#define BULK_CHECKIN_H
-extern int index_bulk_checkin(unsigned char sha1[],
+extern int index_bulk_checkin(struct object_id *oid,
int fd, size_t size, enum object_type type,
const char *path, unsigned flags);
if (revs->max_age == -1 && revs->min_age == -1)
goto out;
- buf = read_sha1_file(tag->oid.hash, &type, &size);
+ buf = read_object_file(&tag->oid, &type, &size);
if (!buf)
goto out;
line = memmem(buf, size, "\ntagger ", 8);
struct cache_tree_sub *sub = NULL;
const char *path, *slash;
int pathlen, entlen;
- const unsigned char *sha1;
+ const struct object_id *oid;
unsigned mode;
int expected_missing = 0;
int contains_ita = 0;
die("cache-tree.c: '%.*s' in '%s' not found",
entlen, path + baselen, path);
i += sub->count;
- sha1 = sub->cache_tree->oid.hash;
+ oid = &sub->cache_tree->oid;
mode = S_IFDIR;
contains_ita = sub->cache_tree->entry_count < 0;
if (contains_ita) {
}
}
else {
- sha1 = ce->oid.hash;
+ oid = &ce->oid;
mode = ce->ce_mode;
entlen = pathlen - baselen;
i++;
}
- if (is_null_sha1(sha1) ||
- (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1))) {
+ if (is_null_oid(oid) ||
+ (mode != S_IFGITLINK && !missing_ok && !has_object_file(oid))) {
strbuf_release(&buffer);
if (expected_missing)
return -1;
return error("invalid object %06o %s for '%.*s'",
- mode, sha1_to_hex(sha1), entlen+baselen, path);
+ mode, oid_to_hex(oid), entlen+baselen, path);
}
/*
/*
* "sub" can be an empty tree if all subentries are i-t-a.
*/
- if (contains_ita && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))
+ if (contains_ita && !oidcmp(oid, &empty_tree_oid))
continue;
strbuf_grow(&buffer, entlen + 100);
strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
- strbuf_add(&buffer, sha1, 20);
+ strbuf_add(&buffer, oid->hash, the_hash_algo->rawsz);
#if DEBUG
fprintf(stderr, "cache-tree update-one %o %.*s\n",
if (repair) {
struct object_id oid;
hash_object_file(buffer.buf, buffer.len, tree_type, &oid);
- if (has_sha1_file(oid.hash))
+ if (has_object_file(&oid))
oidcpy(&it->oid, &oid);
else
to_invalidate = 1;
#endif
if (0 <= it->entry_count) {
- strbuf_add(buffer, it->oid.hash, 20);
+ strbuf_add(buffer, it->oid.hash, the_hash_algo->rawsz);
}
for (i = 0; i < it->subtree_nr; i++) {
struct cache_tree_sub *down = it->down[i];
char *ep;
struct cache_tree *it;
int i, subtree_nr;
+ const unsigned rawsz = the_hash_algo->rawsz;
it = NULL;
/* skip name, but make sure name exists */
goto free_return;
buf++; size--;
if (0 <= it->entry_count) {
- if (size < 20)
+ if (size < rawsz)
goto free_return;
- hashcpy(it->oid.hash, (const unsigned char*)buf);
- buf += 20;
- size -= 20;
+ memcpy(it->oid.hash, (const unsigned char*)buf, rawsz);
+ buf += rawsz;
+ size -= rawsz;
}
#if DEBUG
return it;
}
-int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
+int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
{
int entries, was_valid;
struct lock_file lock_file = LOCK_INIT;
ret = WRITE_TREE_PREFIX_ERROR;
goto out;
}
- hashcpy(sha1, subtree->oid.hash);
+ oidcpy(oid, &subtree->oid);
}
else
- hashcpy(sha1, index_state->cache_tree->oid.hash);
+ oidcpy(oid, &index_state->cache_tree->oid);
out:
rollback_lock_file(&lock_file);
return ret;
}
-int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
+int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix)
{
- return write_index_as_tree(sha1, &the_index, get_index_file(), flags, prefix);
+ return write_index_as_tree(oid, &the_index, get_index_file(), flags, prefix);
}
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
#define WRITE_TREE_UNMERGED_INDEX (-2)
#define WRITE_TREE_PREFIX_ERROR (-3)
-int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
-int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix);
+int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
+int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix);
void prime_cache_tree(struct index_state *, struct tree *);
extern int cache_tree_matches_traversal(struct cache_tree *, struct name_entry *ent, struct traverse_info *info);
*/
extern const char * const local_repo_env[];
-extern void setup_git_env(void);
+extern void setup_git_env(const char *git_dir);
/*
* Returns true iff we have a configured git repository (either via
#define DATA_CHANGED 0x0020
#define TYPE_CHANGED 0x0040
-/*
- * Put in `buf` the name of the file in the local object database that
- * would be used to store a loose object with the specified sha1.
- */
-extern void sha1_file_name(struct strbuf *buf, const unsigned char *sha1);
-
/*
* Return an abbreviated sha1 unique within this repository's object database.
* The result will be at least `len` characters long, and will be NUL
* more calls to find_unique_abbrev are made.
*
* The `_r` variant writes to a buffer supplied by the caller, which must be at
- * least `GIT_SHA1_HEXSZ + 1` bytes. The return value is the number of bytes
+ * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
* written (excluding the NUL terminator).
*
* Note that while this version avoids the static buffer, it is not fully
* reentrant, as it calls into other non-reentrant git code.
*/
-extern const char *find_unique_abbrev(const unsigned char *sha1, int len);
-extern int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len);
+extern const char *find_unique_abbrev(const struct object_id *oid, int len);
+extern int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len);
extern const unsigned char null_sha1[GIT_MAX_RAWSZ];
extern const struct object_id null_oid;
*/
extern char *xdg_cache_home(const char *filename);
-extern void *read_sha1_file_extended(const unsigned char *sha1,
- enum object_type *type,
- unsigned long *size, int lookup_replace);
-static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
+extern void *read_object_file_extended(const struct object_id *oid,
+ enum object_type *type,
+ unsigned long *size, int lookup_replace);
+static inline void *read_object_file(const struct object_id *oid, enum object_type *type, unsigned long *size)
{
- return read_sha1_file_extended(sha1, type, size, 1);
+ return read_object_file_extended(oid, type, size, 1);
}
/*
* This internal function is only declared here for the benefit of
* lookup_replace_object(). Please do not call it directly.
*/
-extern const unsigned char *do_lookup_replace_object(const unsigned char *sha1);
+extern const struct object_id *do_lookup_replace_object(const struct object_id *oid);
/*
* If object sha1 should be replaced, return the replacement object's
* either sha1 or a pointer to a permanently-allocated value. When
* object replacement is suppressed, always return sha1.
*/
-static inline const unsigned char *lookup_replace_object(const unsigned char *sha1)
+static inline const struct object_id *lookup_replace_object(const struct object_id *oid)
{
if (!check_replace_refs)
- return sha1;
- return do_lookup_replace_object(sha1);
+ return oid;
+ return do_lookup_replace_object(oid);
}
-/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
-extern int sha1_object_info(const unsigned char *, unsigned long *);
+/* Read and unpack an object file into memory, write memory to an object file */
+extern int oid_object_info(const struct object_id *, unsigned long *);
extern int hash_object_file(const void *buf, unsigned long len,
const char *type, struct object_id *oid);
extern int git_open_cloexec(const char *name, int flags);
#define git_open(name) git_open_cloexec(name, O_RDONLY)
-extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
-extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
+extern int check_object_signature(const struct object_id *oid, void *buf, unsigned long size, const char *type);
extern int finalize_object_file(const char *tmpfile, const char *filename);
/*
- * Open the loose object at path, check its sha1, and return the contents,
+ * Open the loose object at path, check its hash, and return the contents,
* type, and size. If the object is a blob, then "contents" may return NULL,
* to allow streaming of large blobs.
*
* Returns 0 on success, negative on error (details may be written to stderr).
*/
int read_loose_object(const char *path,
- const unsigned char *expected_sha1,
+ const struct object_id *expected_oid,
enum object_type *type,
unsigned long *size,
void **contents);
*/
extern int has_loose_object_nonlocal(const unsigned char *sha1);
-extern void assert_sha1_type(const unsigned char *sha1, enum object_type expect);
+extern void assert_oid_type(const struct object_id *oid, enum object_type expect);
/* Helper to check and "touch" a file */
extern int check_and_freshen_file(const char *fn, int freshen);
extern int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
extern int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
-extern void *read_object_with_reference(const unsigned char *sha1,
+extern void *read_object_with_reference(const struct object_id *oid,
const char *required_type,
unsigned long *size,
- unsigned char *sha1_ret);
+ struct object_id *oid_ret);
extern struct object *peel_to_type(const char *name, int namelen,
struct object *o, enum object_type);
extern void schedule_dir_for_removal(const char *name, int len);
extern void remove_scheduled_dirs(void);
-extern struct alternate_object_database {
- struct alternate_object_database *next;
-
- /* see alt_scratch_buf() */
- struct strbuf scratch;
- size_t base_len;
-
- /*
- * Used to store the results of readdir(3) calls when searching
- * for unique abbreviated hashes. This cache is never
- * invalidated, thus it's racy and not necessarily accurate.
- * That's fine for its purpose; don't use it for tasks requiring
- * greater accuracy!
- */
- char loose_objects_subdir_seen[256];
- struct oid_array loose_objects_cache;
-
- char path[FLEX_ARRAY];
-} *alt_odb_list;
-extern void prepare_alt_odb(void);
-extern char *compute_alternate_path(const char *path, struct strbuf *err);
-typedef int alt_odb_fn(struct alternate_object_database *, void *);
-extern int foreach_alt_odb(alt_odb_fn, void*);
-
-/*
- * Allocate a "struct alternate_object_database" but do _not_ actually
- * add it to the list of alternates.
- */
-struct alternate_object_database *alloc_alt_odb(const char *dir);
-
-/*
- * Add the directory to the on-disk alternates file; the new entry will also
- * take effect in the current process.
- */
-extern void add_to_alternates_file(const char *dir);
-
-/*
- * Add the directory to the in-memory list of alternates (along with any
- * recursive alternates it points to), but do not modify the on-disk alternates
- * file.
- */
-extern void add_to_alternates_memory(const char *dir);
-
-/*
- * Returns a scratch strbuf pre-filled with the alternate object directory,
- * including a trailing slash, which can be used to access paths in the
- * alternate. Always use this over direct access to alt->scratch, as it
- * cleans up any previous use of the scratch buffer.
- */
-extern struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
-
struct pack_window {
struct pack_window *next;
unsigned char *base;
unsigned int inuse_cnt;
};
-extern struct packed_git {
- struct packed_git *next;
- struct list_head mru;
- struct pack_window *windows;
- off_t pack_size;
- const void *index_data;
- size_t index_size;
- uint32_t num_objects;
- uint32_t num_bad_objects;
- unsigned char *bad_object_sha1;
- int index_version;
- time_t mtime;
- int pack_fd;
- unsigned pack_local:1,
- pack_keep:1,
- freshened:1,
- do_not_close:1,
- pack_promisor:1;
- unsigned char sha1[20];
- struct revindex_entry *revindex;
- /* something like ".git/objects/pack/xxxxx.pack" */
- char pack_name[FLEX_ARRAY]; /* more */
-} *packed_git;
-
-/*
- * A most-recently-used ordered version of the packed_git list.
- */
-extern struct list_head packed_git_mru;
-
struct pack_entry {
off_t offset;
unsigned char sha1[20];
#define OBJECT_INFO_SKIP_CACHED 4
/* Do not retry packed storage after checking packed and loose storage */
#define OBJECT_INFO_QUICK 8
-extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags);
+/* Do not check loose object */
+#define OBJECT_INFO_IGNORE_LOOSE 16
+extern int oid_object_info_extended(const struct object_id *, struct object_info *, unsigned flags);
/*
* Set this to 0 to prevent sha1_object_info_extended() from fetching missing
*size = fill_textconv(textconv, df, &blob);
free_filespec(df);
} else {
- blob = read_sha1_file(oid->hash, &type, size);
+ blob = read_object_file(oid, &type, size);
if (type != OBJ_BLOB)
die("object '%s' is not a blob!", oid_to_hex(oid));
}
"", elem->path, line_prefix, c_meta, c_reset);
printf("%s%sindex ", line_prefix, c_meta);
for (i = 0; i < num_parent; i++) {
- abb = find_unique_abbrev(elem->parent[i].oid.hash,
+ abb = find_unique_abbrev(&elem->parent[i].oid,
abbrev);
printf("%s%s", i ? "," : "", abb);
}
- abb = find_unique_abbrev(elem->oid.hash, abbrev);
+ abb = find_unique_abbrev(&elem->oid, abbrev);
printf("..%s%s\n", abb, c_reset);
if (mode_differs) {
if (!ret) {
enum object_type type;
unsigned long size;
- ret = read_sha1_file(commit->object.oid.hash, &type, &size);
+ ret = read_object_file(&commit->object.oid, &type, &size);
if (!ret)
die("cannot read commit object %s",
oid_to_hex(&commit->object.oid));
return -1;
if (item->object.parsed)
return 0;
- buffer = read_sha1_file(item->object.oid.hash, &type, &size);
+ buffer = read_object_file(&item->object.oid, &type, &size);
if (!buffer)
return quiet_on_missing ? -1 :
error("Could not read %s",
desc = merge_remote_util(parent);
if (!desc || !desc->obj)
return;
- buf = read_sha1_file(desc->obj->oid.hash, &type, &size);
+ buf = read_object_file(&desc->obj->oid, &type, &size);
if (!buf || type != OBJ_TAG)
goto free_return;
len = parse_signature(buf, size);
int encoding_is_utf8;
struct strbuf buffer;
- assert_sha1_type(tree->hash, OBJ_TREE);
+ assert_oid_type(tree, OBJ_TREE);
if (memchr(msg, '\0', msg_len))
return error("a NUL byte in commit log message not allowed.");
git_setup_gettext();
+ initialize_the_repository();
+
attr_start();
git_extract_argv0_path(argv[0]);
unsigned long size;
int ret;
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf)
return error("unable to load config blob object '%s'", name);
if (type != OBJ_BLOB) {
# Perl-compatible regular expressions instead of standard or extended
# POSIX regular expressions.
#
-# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
-# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
-# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
-# default in future releases.
+# USE_LIBPCRE is a synonym for USE_LIBPCRE2, define USE_LIBPCRE1
+# instead if you'd like to use the legacy version 1 of the PCRE
+# library. Support for version 1 will likely be removed in some future
+# release of Git, as upstream has all but abandoned it.
#
# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
#
AC_ARG_WITH(libpcre,
-AS_HELP_STRING([--with-libpcre],[synonym for --with-libpcre1]),
+AS_HELP_STRING([--with-libpcre],[synonym for --with-libpcre2]),
if test "$withval" = "no"; then
- USE_LIBPCRE1=
+ USE_LIBPCRE2=
elif test "$withval" = "yes"; then
- USE_LIBPCRE1=YesPlease
+ USE_LIBPCRE2=YesPlease
else
- USE_LIBPCRE1=YesPlease
+ USE_LIBPCRE2=YesPlease
LIBPCREDIR=$withval
AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
- dnl USE_LIBPCRE1 can still be modified below, so don't substitute
+ dnl USE_LIBPCRE2 can still be modified below, so don't substitute
dnl it yet.
GIT_CONF_SUBST([LIBPCREDIR])
fi)
AC_ARG_WITH(libpcre2,
AS_HELP_STRING([--with-libpcre2],[support Perl-compatible regexes via libpcre2 (default is NO)])
AS_HELP_STRING([], [ARG can be also prefix for libpcre library and headers]),
+ if test -n "$USE_LIBPCRE2"; then
+ AC_MSG_ERROR([Only supply one of --with-libpcre or its synonym --with-libpcre2!])
+ fi
+
if test -n "$USE_LIBPCRE1"; then
AC_MSG_ERROR([Only supply one of --with-libpcre1 or --with-libpcre2!])
fi
GIT_STASH_FLAGS($LIBPCREDIR)
AC_CHECK_LIB([pcre], [pcre_version],
-[USE_LIBPCRE=YesPlease],
-[USE_LIBPCRE=])
+[USE_LIBPCRE1=YesPlease],
+[USE_LIBPCRE1=])
GIT_UNSTASH_FLAGS($LIBPCREDIR)
# tell the completion to use commit completion. This also works with aliases
# of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '".
#
+# Compatible with bash 3.2.57.
+#
# You can set the following environment variables to influence the behavior of
# the completion routines:
#
_git_cherry ()
{
+ case "$cur" in
+ --*)
+ __gitcomp_builtin cherry
+ return
+ esac
+
__git_complete_refs
}
esac
}
-_git_gc ()
-{
- case "$cur" in
- --*)
- __gitcomp_builtin gc
- return
- ;;
- esac
-}
-
_git_gitk ()
{
_gitk
_git_ls_tree ()
{
+ case "$cur" in
+ --*)
+ __gitcomp_builtin ls-tree
+ return
+ ;;
+ esac
+
__git_complete_file
}
fi
}
-_git_name_rev ()
-{
- __gitcomp_builtin name-rev
-}
-
_git_notes ()
{
local subcommands='add append copy edit get-ref list merge prune remove show'
fi
}
+__git_complete_common () {
+ local command="$1"
+
+ case "$cur" in
+ --*)
+ __gitcomp_builtin "$command"
+ ;;
+ esac
+}
+
+__git_cmds_with_parseopt_helper=
+__git_support_parseopt_helper () {
+ test -n "$__git_cmds_with_parseopt_helper" ||
+ __git_cmds_with_parseopt_helper="$(__git --list-parseopt-builtins)"
+
+ case " $__git_cmds_with_parseopt_helper " in
+ *" $1 "*)
+ return 0
+ ;;
+ *)
+ return 1
+ ;;
+ esac
+}
+
+__git_complete_command () {
+ local command="$1"
+ local completion_func="_git_${command//-/_}"
+ if declare -f $completion_func >/dev/null 2>/dev/null; then
+ $completion_func
+ return 0
+ elif __git_support_parseopt_helper "$command"; then
+ __git_complete_common "$command"
+ return 0
+ else
+ return 1
+ fi
+}
+
__git_main ()
{
local i c=1 command __git_dir __git_repo_path
return
fi
- local completion_func="_git_${command//-/_}"
- declare -f $completion_func >/dev/null 2>/dev/null && $completion_func && return
+ __git_complete_command "$command" && return
local expansion=$(__git_aliased_command "$command")
if [ -n "$expansion" ]; then
words[1]=$expansion
- completion_func="_git_${expansion//-/_}"
- declare -f $completion_func >/dev/null 2>/dev/null && $completion_func
+ __git_complete_command "$expansion"
fi
}
my $COLOR = qr/\x1b\[[0-9;]*m/;
my $BORING = qr/$COLOR|\s/;
-# The patch portion of git log -p --graph should only ever have preceding | and
-# not / or \ as merge history only shows up on the commit line.
-my $GRAPH = qr/$COLOR?\|$COLOR?\s+/;
-
my @removed;
my @added;
my $in_hunk;
+my $graph_indent = 0;
our $line_cb = sub { print @_ };
our $flush_cb = sub { local $| = 1 };
-sub handle_line {
+# Count the visible width of a string, excluding any terminal color sequences.
+sub visible_width {
local $_ = shift;
+ my $ret = 0;
+ while (length) {
+ if (s/^$COLOR//) {
+ # skip colors
+ } elsif (s/^.//) {
+ $ret++;
+ }
+ }
+ return $ret;
+}
+
+# Return a substring of $str, omitting $len visible characters from the
+# beginning, where terminal color sequences do not count as visible.
+sub visible_substr {
+ my ($str, $len) = @_;
+ while ($len > 0) {
+ if ($str =~ s/^$COLOR//) {
+ next
+ }
+ $str =~ s/^.//;
+ $len--;
+ }
+ return $str;
+}
+
+sub handle_line {
+ my $orig = shift;
+ local $_ = $orig;
+
+ # match a graph line that begins a commit
+ if (/^(?:$COLOR?\|$COLOR?[ ])* # zero or more leading "|" with space
+ $COLOR?\*$COLOR?[ ] # a "*" with its trailing space
+ (?:$COLOR?\|$COLOR?[ ])* # zero or more trailing "|"
+ [ ]* # trailing whitespace for merges
+ /x) {
+ my $graph_prefix = $&;
+
+ # We must flush before setting graph indent, since the
+ # new commit may be indented differently from what we
+ # queued.
+ flush();
+ $graph_indent = visible_width($graph_prefix);
+
+ } elsif ($graph_indent) {
+ if (length($_) < $graph_indent) {
+ $graph_indent = 0;
+ } else {
+ $_ = visible_substr($_, $graph_indent);
+ }
+ }
if (!$in_hunk) {
- $line_cb->($_);
- $in_hunk = /^$GRAPH*$COLOR*\@\@ /;
+ $line_cb->($orig);
+ $in_hunk = /^$COLOR*\@\@ /;
}
- elsif (/^$GRAPH*$COLOR*-/) {
- push @removed, $_;
+ elsif (/^$COLOR*-/) {
+ push @removed, $orig;
}
- elsif (/^$GRAPH*$COLOR*\+/) {
- push @added, $_;
+ elsif (/^$COLOR*\+/) {
+ push @added, $orig;
}
else {
- show_hunk(\@removed, \@added);
- @removed = ();
- @added = ();
-
- $line_cb->($_);
- $in_hunk = /^$GRAPH*$COLOR*[\@ ]/;
+ flush();
+ $line_cb->($orig);
+ $in_hunk = /^$COLOR*[\@ ]/;
}
# Most of the time there is enough output to keep things streaming,
# Flush any queued hunk (this can happen when there is no trailing
# context in the final diff of the input).
show_hunk(\@removed, \@added);
+ @removed = ();
+ @added = ();
}
sub highlight_stdin {
my $suffix_a = join('', @$a[($sa+1)..$#$a]);
my $suffix_b = join('', @$b[($sb+1)..$#$b]);
- return $prefix_a !~ /^$GRAPH*$COLOR*-$BORING*$/ ||
- $prefix_b !~ /^$GRAPH*$COLOR*\+$BORING*$/ ||
+ return visible_substr($prefix_a, $graph_indent) !~ /^$COLOR*-$BORING*$/ ||
+ visible_substr($prefix_b, $graph_indent) !~ /^$COLOR*\+$BORING*$/ ||
$suffix_a !~ /^$BORING*$/ ||
$suffix_b !~ /^$BORING*$/;
}
# dh_test_setup_history generates a contrived graph such that we have at least
# 1 nesting (E) and 2 nestings (F).
#
-# A branch
-# /
-# D---E---F master
+# A---B master
+# /
+# D---E---F branch
#
# git log --all --graph
# * commit
-# | A
+# | B
# | * commit
# | | F
+# * | commit
+# | | A
# | * commit
# |/
# | E
# D
#
dh_test_setup_history () {
- echo "file1" >file1 &&
- echo "file2" >file2 &&
- echo "file3" >file3 &&
-
- cat file1 >file &&
+ echo file1 >file &&
git add file &&
+ test_tick &&
git commit -m "D" &&
git checkout -b branch &&
- cat file2 >file &&
- git commit -a -m "A" &&
+ echo file2 >file &&
+ test_tick &&
+ git commit -a -m "E" &&
git checkout master &&
- cat file2 >file &&
- git commit -a -m "E" &&
+ echo file2 >file &&
+ test_tick &&
+ git commit -a -m "A" &&
- cat file3 >file &&
- git commit -a -m "F"
+ git checkout branch &&
+ echo file3 >file &&
+ test_tick &&
+ git commit -a -m "F" &&
+
+ git checkout master &&
+ echo file3 >file &&
+ test_tick &&
+ git commit -a -m "B"
}
left_trim () {
test_expect_success 'diff-highlight works with the --graph option' '
dh_test_setup_history &&
- # topo-order so that the order of the commits is the same as with --graph
+ # date-order so that the commits are interleaved for both
# trim graph elements so we can do a diff
# trim leading space because our trim_graph is not perfect
- git log --branches -p --topo-order |
+ git log --branches -p --date-order |
"$DIFF_HIGHLIGHT" | left_trim >graph.exp &&
- git log --branches -p --graph |
+ git log --branches -p --date-order --graph |
"$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph.act &&
test_cmp graph.exp graph.act
'
+# Just reuse the previous graph test, but with --color. Our trimming
+# doesn't know about color, so just sanity check that something got
+# highlighted.
+test_expect_success 'diff-highlight works with color graph' '
+ git log --branches -p --date-order --graph --color |
+ "$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph &&
+ grep "\[7m" graph
+'
+
# Most combined diffs won't meet diff-highlight's line-number filter. So we
# create one here where one side drops a line and the other modifies it. That
# should result in a diff like:
test_cmp expect actual
'
+test_expect_success 'diff-highlight handles --graph with leading dash' '
+ cat >file <<-\EOF &&
+ before
+ the old line
+ -leading dash
+ EOF
+ git add file &&
+ git commit -m before &&
+
+ sed s/old/new/ <file >file.tmp &&
+ mv file.tmp file &&
+ git add file &&
+ git commit -m after &&
+
+ cat >expect <<-EOF &&
+ --- a/file
+ +++ b/file
+ @@ -1,3 +1,3 @@
+ before
+ -the ${CW}old${CR} line
+ +the ${CW}new${CR} line
+ -leading dash
+ EOF
+ git log --graph -p -1 | "$DIFF_HIGHLIGHT" >actual.raw &&
+ trim_graph <actual.raw | sed -n "/^---/,\$p" >actual &&
+ test_cmp expect actual
+'
+
test_done
-These are original scripted implementations, kept primarily for their
-reference value to any aspiring plumbing users who want to learn how
-pieces can be fit together.
+This directory used to contain scripted implementations of builtins
+that have since been rewritten in C.
+
+They have now been removed, but can be retrieved from an older commit
+that removed them from this directory.
+
+They're interesting for their reference value to any aspiring plumbing
+users who want to learn how pieces can be fit together, but in many
+cases have drifted enough from the actual implementations Git uses to
+be instructive.
+
+Other things that can be useful:
+
+ * Some commands such as git-gc wrap other commands, and what they're
+ doing behind the scenes can be seen by running them under
+ GIT_TRACE=1
+
+ * Doing `git log` on paths matching '*--helper.c' will show
+ incremental effort in the direction of moving existing shell
+ scripts to C.
+++ /dev/null
-#include "builtin.h"
-#include "cache.h"
-#include "refs.h"
-#include "commit.h"
-#include "sigchain.h"
-
-static char *get_stdin(void)
-{
- struct strbuf buf = STRBUF_INIT;
- if (strbuf_read(&buf, 0, 1024) < 0) {
- die_errno("error reading standard input");
- }
- return strbuf_detach(&buf, NULL);
-}
-
-static void show_new(enum object_type type, unsigned char *sha1_new)
-{
- fprintf(stderr, " %s: %s\n", type_name(type),
- find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
-}
-
-static int update_ref_env(const char *action,
- const char *refname,
- unsigned char *sha1,
- unsigned char *oldval)
-{
- char msg[1024];
- const char *rla = getenv("GIT_REFLOG_ACTION");
-
- if (!rla)
- rla = "(reflog update)";
- if (snprintf(msg, sizeof(msg), "%s: %s", rla, action) >= sizeof(msg))
- warning("reflog message too long: %.*s...", 50, msg);
- return update_ref(msg, refname, sha1, oldval, 0,
- UPDATE_REFS_QUIET_ON_ERR);
-}
-
-static int update_local_ref(const char *name,
- const char *new_head,
- const char *note,
- int verbose, int force)
-{
- unsigned char sha1_old[20], sha1_new[20];
- char oldh[41], newh[41];
- struct commit *current, *updated;
- enum object_type type;
-
- if (get_sha1_hex(new_head, sha1_new))
- die("malformed object name %s", new_head);
-
- type = sha1_object_info(sha1_new, NULL);
- if (type < 0)
- die("object %s not found", new_head);
-
- if (!*name) {
- /* Not storing */
- if (verbose) {
- fprintf(stderr, "* fetched %s\n", note);
- show_new(type, sha1_new);
- }
- return 0;
- }
-
- if (get_sha1(name, sha1_old)) {
- const char *msg;
- just_store:
- /* new ref */
- if (!strncmp(name, "refs/tags/", 10))
- msg = "storing tag";
- else
- msg = "storing head";
- fprintf(stderr, "* %s: storing %s\n",
- name, note);
- show_new(type, sha1_new);
- return update_ref_env(msg, name, sha1_new, NULL);
- }
-
- if (!hashcmp(sha1_old, sha1_new)) {
- if (verbose) {
- fprintf(stderr, "* %s: same as %s\n", name, note);
- show_new(type, sha1_new);
- }
- return 0;
- }
-
- if (!strncmp(name, "refs/tags/", 10)) {
- fprintf(stderr, "* %s: updating with %s\n", name, note);
- show_new(type, sha1_new);
- return update_ref_env("updating tag", name, sha1_new, NULL);
- }
-
- current = lookup_commit_reference(sha1_old);
- updated = lookup_commit_reference(sha1_new);
- if (!current || !updated)
- goto just_store;
-
- strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
- strcpy(newh, find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
-
- if (in_merge_bases(current, updated)) {
- fprintf(stderr, "* %s: fast-forward to %s\n",
- name, note);
- fprintf(stderr, " old..new: %s..%s\n", oldh, newh);
- return update_ref_env("fast-forward", name, sha1_new, sha1_old);
- }
- if (!force) {
- fprintf(stderr,
- "* %s: not updating to non-fast-forward %s\n",
- name, note);
- fprintf(stderr,
- " old...new: %s...%s\n", oldh, newh);
- return 1;
- }
- fprintf(stderr,
- "* %s: forcing update to non-fast-forward %s\n",
- name, note);
- fprintf(stderr, " old...new: %s...%s\n", oldh, newh);
- return update_ref_env("forced-update", name, sha1_new, sha1_old);
-}
-
-static int append_fetch_head(FILE *fp,
- const char *head, const char *remote,
- const char *remote_name, const char *remote_nick,
- const char *local_name, int not_for_merge,
- int verbose, int force)
-{
- struct commit *commit;
- int remote_len, i, note_len;
- unsigned char sha1[20];
- char note[1024];
- const char *what, *kind;
-
- if (get_sha1(head, sha1))
- return error("Not a valid object name: %s", head);
- commit = lookup_commit_reference_gently(sha1, 1);
- if (!commit)
- not_for_merge = 1;
-
- if (!strcmp(remote_name, "HEAD")) {
- kind = "";
- what = "";
- }
- else if (!strncmp(remote_name, "refs/heads/", 11)) {
- kind = "branch";
- what = remote_name + 11;
- }
- else if (!strncmp(remote_name, "refs/tags/", 10)) {
- kind = "tag";
- what = remote_name + 10;
- }
- else if (!strncmp(remote_name, "refs/remotes/", 13)) {
- kind = "remote-tracking branch";
- what = remote_name + 13;
- }
- else {
- kind = "";
- what = remote_name;
- }
-
- remote_len = strlen(remote);
- for (i = remote_len - 1; remote[i] == '/' && 0 <= i; i--)
- ;
- remote_len = i + 1;
- if (4 < i && !strncmp(".git", remote + i - 3, 4))
- remote_len = i - 3;
-
- note_len = 0;
- if (*what) {
- if (*kind)
- note_len += sprintf(note + note_len, "%s ", kind);
- note_len += sprintf(note + note_len, "'%s' of ", what);
- }
- note_len += sprintf(note + note_len, "%.*s", remote_len, remote);
- fprintf(fp, "%s\t%s\t%s\n",
- sha1_to_hex(commit ? commit->object.sha1 : sha1),
- not_for_merge ? "not-for-merge" : "",
- note);
- return update_local_ref(local_name, head, note, verbose, force);
-}
-
-static char *keep;
-static void remove_keep(void)
-{
- if (keep && *keep)
- unlink(keep);
-}
-
-static void remove_keep_on_signal(int signo)
-{
- remove_keep();
- sigchain_pop(signo);
- raise(signo);
-}
-
-static char *find_local_name(const char *remote_name, const char *refs,
- int *force_p, int *not_for_merge_p)
-{
- const char *ref = refs;
- int len = strlen(remote_name);
-
- while (ref) {
- const char *next;
- int single_force, not_for_merge;
-
- while (*ref == '\n')
- ref++;
- if (!*ref)
- break;
- next = strchr(ref, '\n');
-
- single_force = not_for_merge = 0;
- if (*ref == '+') {
- single_force = 1;
- ref++;
- }
- if (*ref == '.') {
- not_for_merge = 1;
- ref++;
- if (*ref == '+') {
- single_force = 1;
- ref++;
- }
- }
- if (!strncmp(remote_name, ref, len) && ref[len] == ':') {
- const char *local_part = ref + len + 1;
- int retlen;
-
- if (!next)
- retlen = strlen(local_part);
- else
- retlen = next - local_part;
- *force_p = single_force;
- *not_for_merge_p = not_for_merge;
- return xmemdupz(local_part, retlen);
- }
- ref = next;
- }
- return NULL;
-}
-
-static int fetch_native_store(FILE *fp,
- const char *remote,
- const char *remote_nick,
- const char *refs,
- int verbose, int force)
-{
- char buffer[1024];
- int err = 0;
-
- sigchain_push_common(remove_keep_on_signal);
- atexit(remove_keep);
-
- while (fgets(buffer, sizeof(buffer), stdin)) {
- int len;
- char *cp;
- char *local_name;
- int single_force, not_for_merge;
-
- for (cp = buffer; *cp && !isspace(*cp); cp++)
- ;
- if (*cp)
- *cp++ = 0;
- len = strlen(cp);
- if (len && cp[len-1] == '\n')
- cp[--len] = 0;
- if (!strcmp(buffer, "failed"))
- die("Fetch failure: %s", remote);
- if (!strcmp(buffer, "pack"))
- continue;
- if (!strcmp(buffer, "keep")) {
- char *od = get_object_directory();
- int len = strlen(od) + strlen(cp) + 50;
- keep = xmalloc(len);
- sprintf(keep, "%s/pack/pack-%s.keep", od, cp);
- continue;
- }
-
- local_name = find_local_name(cp, refs,
- &single_force, ¬_for_merge);
- if (!local_name)
- continue;
- err |= append_fetch_head(fp,
- buffer, remote, cp, remote_nick,
- local_name, not_for_merge,
- verbose, force || single_force);
- }
- return err;
-}
-
-static int parse_reflist(const char *reflist)
-{
- const char *ref;
-
- printf("refs='");
- for (ref = reflist; ref; ) {
- const char *next;
- while (*ref && isspace(*ref))
- ref++;
- if (!*ref)
- break;
- for (next = ref; *next && !isspace(*next); next++)
- ;
- printf("\n%.*s", (int)(next - ref), ref);
- ref = next;
- }
- printf("'\n");
-
- printf("rref='");
- for (ref = reflist; ref; ) {
- const char *next, *colon;
- while (*ref && isspace(*ref))
- ref++;
- if (!*ref)
- break;
- for (next = ref; *next && !isspace(*next); next++)
- ;
- if (*ref == '.')
- ref++;
- if (*ref == '+')
- ref++;
- colon = strchr(ref, ':');
- putchar('\n');
- printf("%.*s", (int)((colon ? colon : next) - ref), ref);
- ref = next;
- }
- printf("'\n");
- return 0;
-}
-
-static int expand_refs_wildcard(const char *ls_remote_result, int numrefs,
- const char **refs)
-{
- int i, matchlen, replacelen;
- int found_one = 0;
- const char *remote = *refs++;
- numrefs--;
-
- if (numrefs == 0) {
- fprintf(stderr, "Nothing specified for fetching with remote.%s.fetch\n",
- remote);
- printf("empty\n");
- }
-
- for (i = 0; i < numrefs; i++) {
- const char *ref = refs[i];
- const char *lref = ref;
- const char *colon;
- const char *tail;
- const char *ls;
- const char *next;
-
- if (*lref == '+')
- lref++;
- colon = strchr(lref, ':');
- tail = lref + strlen(lref);
- if (!(colon &&
- 2 < colon - lref &&
- colon[-1] == '*' &&
- colon[-2] == '/' &&
- 2 < tail - (colon + 1) &&
- tail[-1] == '*' &&
- tail[-2] == '/')) {
- /* not a glob */
- if (!found_one++)
- printf("explicit\n");
- printf("%s\n", ref);
- continue;
- }
-
- /* glob */
- if (!found_one++)
- printf("glob\n");
-
- /* lref to colon-2 is remote hierarchy name;
- * colon+1 to tail-2 is local.
- */
- matchlen = (colon-1) - lref;
- replacelen = (tail-1) - (colon+1);
- for (ls = ls_remote_result; ls; ls = next) {
- const char *eol;
- unsigned char sha1[20];
- int namelen;
-
- while (*ls && isspace(*ls))
- ls++;
- next = strchr(ls, '\n');
- eol = !next ? (ls + strlen(ls)) : next;
- if (!memcmp("^{}", eol-3, 3))
- continue;
- if (eol - ls < 40)
- continue;
- if (get_sha1_hex(ls, sha1))
- continue;
- ls += 40;
- while (ls < eol && isspace(*ls))
- ls++;
- /* ls to next (or eol) is the name.
- * is it identical to lref to colon-2?
- */
- if ((eol - ls) <= matchlen ||
- strncmp(ls, lref, matchlen))
- continue;
-
- /* Yes, it is a match */
- namelen = eol - ls;
- if (lref != ref)
- putchar('+');
- printf("%.*s:%.*s%.*s\n",
- namelen, ls,
- replacelen, colon + 1,
- namelen - matchlen, ls + matchlen);
- }
- }
- return 0;
-}
-
-static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_result)
-{
- int err = 0;
- int lrr_count = lrr_count, i, pass;
- const char *cp;
- struct lrr {
- const char *line;
- const char *name;
- int namelen;
- int shown;
- } *lrr_list = lrr_list;
-
- for (pass = 0; pass < 2; pass++) {
- /* pass 0 counts and allocates, pass 1 fills... */
- cp = ls_remote_result;
- i = 0;
- while (1) {
- const char *np;
- while (*cp && isspace(*cp))
- cp++;
- if (!*cp)
- break;
- np = strchrnul(cp, '\n');
- if (pass) {
- lrr_list[i].line = cp;
- lrr_list[i].name = cp + 41;
- lrr_list[i].namelen = np - (cp + 41);
- }
- i++;
- cp = np;
- }
- if (!pass) {
- lrr_count = i;
- lrr_list = xcalloc(lrr_count, sizeof(*lrr_list));
- }
- }
-
- while (1) {
- const char *next;
- int rreflen;
- int i;
-
- while (*rref && isspace(*rref))
- rref++;
- if (!*rref)
- break;
- next = strchrnul(rref, '\n');
- rreflen = next - rref;
-
- for (i = 0; i < lrr_count; i++) {
- struct lrr *lrr = &(lrr_list[i]);
-
- if (rreflen == lrr->namelen &&
- !memcmp(lrr->name, rref, rreflen)) {
- if (!lrr->shown)
- printf("%.*s\n",
- sha1_only ? 40 : lrr->namelen + 41,
- lrr->line);
- lrr->shown = 1;
- break;
- }
- }
- if (lrr_count <= i) {
- error("pick-rref: %.*s not found", rreflen, rref);
- err = 1;
- }
- rref = next;
- }
- free(lrr_list);
- return err;
-}
-
-int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
-{
- int verbose = 0;
- int force = 0;
- int sopt = 0;
-
- while (1 < argc) {
- const char *arg = argv[1];
- if (!strcmp("-v", arg))
- verbose = 1;
- else if (!strcmp("-f", arg))
- force = 1;
- else if (!strcmp("-s", arg))
- sopt = 1;
- else
- break;
- argc--;
- argv++;
- }
-
- if (argc <= 1)
- return error("Missing subcommand");
-
- if (!strcmp("append-fetch-head", argv[1])) {
- int result;
- FILE *fp;
- char *filename;
-
- if (argc != 8)
- return error("append-fetch-head takes 6 args");
- filename = git_path_fetch_head();
- fp = fopen(filename, "a");
- if (!fp)
- return error("cannot open %s: %s", filename, strerror(errno));
- result = append_fetch_head(fp, argv[2], argv[3],
- argv[4], argv[5],
- argv[6], !!argv[7][0],
- verbose, force);
- fclose(fp);
- return result;
- }
- if (!strcmp("native-store", argv[1])) {
- int result;
- FILE *fp;
- char *filename;
-
- if (argc != 5)
- return error("fetch-native-store takes 3 args");
- filename = git_path_fetch_head();
- fp = fopen(filename, "a");
- if (!fp)
- return error("cannot open %s: %s", filename, strerror(errno));
- result = fetch_native_store(fp, argv[2], argv[3], argv[4],
- verbose, force);
- fclose(fp);
- return result;
- }
- if (!strcmp("parse-reflist", argv[1])) {
- const char *reflist;
- if (argc != 3)
- return error("parse-reflist takes 1 arg");
- reflist = argv[2];
- if (!strcmp(reflist, "-"))
- reflist = get_stdin();
- return parse_reflist(reflist);
- }
- if (!strcmp("pick-rref", argv[1])) {
- const char *ls_remote_result;
- if (argc != 4)
- return error("pick-rref takes 2 args");
- ls_remote_result = argv[3];
- if (!strcmp(ls_remote_result, "-"))
- ls_remote_result = get_stdin();
- return pick_rref(sopt, argv[2], ls_remote_result);
- }
- if (!strcmp("expand-refs-wildcard", argv[1])) {
- const char *reflist;
- if (argc < 4)
- return error("expand-refs-wildcard takes at least 2 args");
- reflist = argv[2];
- if (!strcmp(reflist, "-"))
- reflist = get_stdin();
- return expand_refs_wildcard(reflist, argc - 3, argv + 3);
- }
-
- return error("Unknown subcommand: %s", argv[1]);
-}
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005, 2006 Junio C Hamano
-
-SUBDIRECTORY_OK=Yes
-OPTIONS_KEEPDASHDASH=
-OPTIONS_STUCKLONG=t
-OPTIONS_SPEC="\
-git am [options] [(<mbox>|<Maildir>)...]
-git am [options] (--continue | --skip | --abort)
---
-i,interactive run interactively
-b,binary* (historical option -- no-op)
-3,3way allow fall back on 3way merging if needed
-q,quiet be quiet
-s,signoff add a Signed-off-by line to the commit message
-u,utf8 recode into utf8 (default)
-k,keep pass -k flag to git-mailinfo
-keep-non-patch pass -b flag to git-mailinfo
-m,message-id pass -m flag to git-mailinfo
-keep-cr pass --keep-cr flag to git-mailsplit for mbox format
-no-keep-cr do not pass --keep-cr flag to git-mailsplit independent of am.keepcr
-c,scissors strip everything before a scissors line
-whitespace= pass it through git-apply
-ignore-space-change pass it through git-apply
-ignore-whitespace pass it through git-apply
-directory= pass it through git-apply
-exclude= pass it through git-apply
-include= pass it through git-apply
-C= pass it through git-apply
-p= pass it through git-apply
-patch-format= format the patch(es) are in
-reject pass it through git-apply
-resolvemsg= override error message when patch failure occurs
-continue continue applying patches after resolving a conflict
-r,resolved synonyms for --continue
-skip skip the current patch
-abort restore the original branch and abort the patching operation.
-committer-date-is-author-date lie about committer date
-ignore-date use current timestamp for author date
-rerere-autoupdate update the index with reused conflict resolution if possible
-S,gpg-sign? GPG-sign commits
-rebasing* (internal use for git-rebase)"
-
-. git-sh-setup
-. git-sh-i18n
-prefix=$(git rev-parse --show-prefix)
-set_reflog_action am
-require_work_tree
-cd_to_toplevel
-
-git var GIT_COMMITTER_IDENT >/dev/null ||
- die "$(gettext "You need to set your committer info first")"
-
-if git rev-parse --verify -q HEAD >/dev/null
-then
- HAS_HEAD=yes
-else
- HAS_HEAD=
-fi
-
-cmdline="git am"
-if test '' != "$interactive"
-then
- cmdline="$cmdline -i"
-fi
-if test '' != "$threeway"
-then
- cmdline="$cmdline -3"
-fi
-
-empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
-
-sq () {
- git rev-parse --sq-quote "$@"
-}
-
-stop_here () {
- echo "$1" >"$dotest/next"
- git rev-parse --verify -q HEAD >"$dotest/abort-safety"
- exit 1
-}
-
-safe_to_abort () {
- if test -f "$dotest/dirtyindex"
- then
- return 1
- fi
-
- if ! test -f "$dotest/abort-safety"
- then
- return 0
- fi
-
- abort_safety=$(cat "$dotest/abort-safety")
- if test "z$(git rev-parse --verify -q HEAD)" = "z$abort_safety"
- then
- return 0
- fi
- gettextln "You seem to have moved HEAD since the last 'am' failure.
-Not rewinding to ORIG_HEAD" >&2
- return 1
-}
-
-stop_here_user_resolve () {
- if [ -n "$resolvemsg" ]; then
- printf '%s\n' "$resolvemsg"
- stop_here $1
- fi
- eval_gettextln "When you have resolved this problem, run \"\$cmdline --continue\".
-If you prefer to skip this patch, run \"\$cmdline --skip\" instead.
-To restore the original branch and stop patching, run \"\$cmdline --abort\"."
-
- stop_here $1
-}
-
-go_next () {
- rm -f "$dotest/$msgnum" "$dotest/msg" "$dotest/msg-clean" \
- "$dotest/patch" "$dotest/info"
- echo "$next" >"$dotest/next"
- this=$next
-}
-
-cannot_fallback () {
- echo "$1"
- gettextln "Cannot fall back to three-way merge."
- exit 1
-}
-
-fall_back_3way () {
- O_OBJECT=$(cd "$GIT_OBJECT_DIRECTORY" && pwd)
-
- rm -fr "$dotest"/patch-merge-*
- mkdir "$dotest/patch-merge-tmp-dir"
-
- # First see if the patch records the index info that we can use.
- cmd="git apply $git_apply_opt --build-fake-ancestor" &&
- cmd="$cmd "'"$dotest/patch-merge-tmp-index" "$dotest/patch"' &&
- eval "$cmd" &&
- GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
- git write-tree >"$dotest/patch-merge-base+" ||
- cannot_fallback "$(gettext "Repository lacks necessary blobs to fall back on 3-way merge.")"
-
- say "$(gettext "Using index info to reconstruct a base tree...")"
-
- cmd='GIT_INDEX_FILE="$dotest/patch-merge-tmp-index"'
-
- if test -z "$GIT_QUIET"
- then
- eval "$cmd git diff-index --cached --diff-filter=AM --name-status HEAD"
- fi
-
- cmd="$cmd git apply --cached $git_apply_opt"' <"$dotest/patch"'
- if eval "$cmd"
- then
- mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
- mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
- else
- cannot_fallback "$(gettext "Did you hand edit your patch?
-It does not apply to blobs recorded in its index.")"
- fi
-
- test -f "$dotest/patch-merge-index" &&
- his_tree=$(GIT_INDEX_FILE="$dotest/patch-merge-index" git write-tree) &&
- orig_tree=$(cat "$dotest/patch-merge-base") &&
- rm -fr "$dotest"/patch-merge-* || exit 1
-
- say "$(gettext "Falling back to patching base and 3-way merge...")"
-
- # This is not so wrong. Depending on which base we picked,
- # orig_tree may be wildly different from ours, but his_tree
- # has the same set of wildly different changes in parts the
- # patch did not touch, so recursive ends up canceling them,
- # saying that we reverted all those changes.
-
- eval GITHEAD_$his_tree='"$FIRSTLINE"'
- export GITHEAD_$his_tree
- if test -n "$GIT_QUIET"
- then
- GIT_MERGE_VERBOSITY=0 && export GIT_MERGE_VERBOSITY
- fi
- our_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree)
- git-merge-recursive $orig_tree -- $our_tree $his_tree || {
- git rerere $allow_rerere_autoupdate
- die "$(gettext "Failed to merge in the changes.")"
- }
- unset GITHEAD_$his_tree
-}
-
-clean_abort () {
- test $# = 0 || echo >&2 "$@"
- rm -fr "$dotest"
- exit 1
-}
-
-patch_format=
-
-check_patch_format () {
- # early return if patch_format was set from the command line
- if test -n "$patch_format"
- then
- return 0
- fi
-
- # we default to mbox format if input is from stdin and for
- # directories
- if test $# = 0 || test "x$1" = "x-" || test -d "$1"
- then
- patch_format=mbox
- return 0
- fi
-
- # otherwise, check the first few non-blank lines of the first
- # patch to try to detect its format
- {
- # Start from first line containing non-whitespace
- l1=
- while test -z "$l1"
- do
- read l1 || break
- done
- read l2
- read l3
- case "$l1" in
- "From "* | "From: "*)
- patch_format=mbox
- ;;
- '# This series applies on GIT commit'*)
- patch_format=stgit-series
- ;;
- "# HG changeset patch")
- patch_format=hg
- ;;
- *)
- # if the second line is empty and the third is
- # a From, Author or Date entry, this is very
- # likely an StGIT patch
- case "$l2,$l3" in
- ,"From: "* | ,"Author: "* | ,"Date: "*)
- patch_format=stgit
- ;;
- *)
- ;;
- esac
- ;;
- esac
- if test -z "$patch_format" &&
- test -n "$l1" &&
- test -n "$l2" &&
- test -n "$l3"
- then
- # This begins with three non-empty lines. Is this a
- # piece of e-mail a-la RFC2822? Grab all the headers,
- # discarding the indented remainder of folded lines,
- # and see if it looks like that they all begin with the
- # header field names...
- tr -d '\015' <"$1" |
- sed -n -e '/^$/q' -e '/^[ ]/d' -e p |
- sane_egrep -v '^[!-9;-~]+:' >/dev/null ||
- patch_format=mbox
- fi
- } < "$1" || clean_abort
-}
-
-split_patches () {
- case "$patch_format" in
- mbox)
- if test t = "$keepcr"
- then
- keep_cr=--keep-cr
- else
- keep_cr=
- fi
- git mailsplit -d"$prec" -o"$dotest" -b $keep_cr -- "$@" > "$dotest/last" ||
- clean_abort
- ;;
- stgit-series)
- if test $# -ne 1
- then
- clean_abort "$(gettext "Only one StGIT patch series can be applied at once")"
- fi
- series_dir=$(dirname "$1")
- series_file="$1"
- shift
- {
- set x
- while read filename
- do
- set "$@" "$series_dir/$filename"
- done
- # remove the safety x
- shift
- # remove the arg coming from the first-line comment
- shift
- } < "$series_file" || clean_abort
- # set the patch format appropriately
- patch_format=stgit
- # now handle the actual StGIT patches
- split_patches "$@"
- ;;
- stgit)
- this=0
- test 0 -eq "$#" && set -- -
- for stgit in "$@"
- do
- this=$(expr "$this" + 1)
- msgnum=$(printf "%0${prec}d" $this)
- # Perl version of StGIT parse_patch. The first nonemptyline
- # not starting with Author, From or Date is the
- # subject, and the body starts with the next nonempty
- # line not starting with Author, From or Date
- @@PERL@@ -ne 'BEGIN { $subject = 0 }
- if ($subject > 1) { print ; }
- elsif (/^\s+$/) { next ; }
- elsif (/^Author:/) { s/Author/From/ ; print ;}
- elsif (/^(From|Date)/) { print ; }
- elsif ($subject) {
- $subject = 2 ;
- print "\n" ;
- print ;
- } else {
- print "Subject: ", $_ ;
- $subject = 1;
- }
- ' -- "$stgit" >"$dotest/$msgnum" || clean_abort
- done
- echo "$this" > "$dotest/last"
- this=
- msgnum=
- ;;
- hg)
- this=0
- test 0 -eq "$#" && set -- -
- for hg in "$@"
- do
- this=$(( $this + 1 ))
- msgnum=$(printf "%0${prec}d" $this)
- # hg stores changeset metadata in #-commented lines preceding
- # the commit message and diff(s). The only metadata we care about
- # are the User and Date (Node ID and Parent are hashes which are
- # only relevant to the hg repository and thus not useful to us)
- # Since we cannot guarantee that the commit message is in
- # git-friendly format, we put no Subject: line and just consume
- # all of the message as the body
- LANG=C LC_ALL=C @@PERL@@ -M'POSIX qw(strftime)' -ne 'BEGIN { $subject = 0 }
- if ($subject) { print ; }
- elsif (/^\# User /) { s/\# User/From:/ ; print ; }
- elsif (/^\# Date /) {
- my ($hashsign, $str, $time, $tz) = split ;
- $tz_str = sprintf "%+05d", (0-$tz)/36;
- print "Date: " .
- strftime("%a, %d %b %Y %H:%M:%S ",
- gmtime($time-$tz))
- . "$tz_str\n";
- } elsif (/^\# /) { next ; }
- else {
- print "\n", $_ ;
- $subject = 1;
- }
- ' -- "$hg" >"$dotest/$msgnum" || clean_abort
- done
- echo "$this" >"$dotest/last"
- this=
- msgnum=
- ;;
- *)
- if test -n "$patch_format"
- then
- clean_abort "$(eval_gettext "Patch format \$patch_format is not supported.")"
- else
- clean_abort "$(gettext "Patch format detection failed.")"
- fi
- ;;
- esac
-}
-
-prec=4
-dotest="$GIT_DIR/rebase-apply"
-sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
-messageid= resolvemsg= resume= scissors= no_inbody_headers=
-git_apply_opt=
-committer_date_is_author_date=
-ignore_date=
-allow_rerere_autoupdate=
-gpg_sign_opt=
-threeway=
-
-if test "$(git config --bool --get am.messageid)" = true
-then
- messageid=t
-fi
-
-if test "$(git config --bool --get am.keepcr)" = true
-then
- keepcr=t
-fi
-
-while test $# != 0
-do
- case "$1" in
- -i|--interactive)
- interactive=t ;;
- -b|--binary)
- gettextln >&2 "The -b/--binary option has been a no-op for long time, and
-it will be removed. Please do not use it anymore."
- ;;
- -3|--3way)
- threeway=t ;;
- -s|--signoff)
- sign=t ;;
- -u|--utf8)
- utf8=t ;; # this is now default
- --no-utf8)
- utf8= ;;
- -m|--message-id)
- messageid=t ;;
- --no-message-id)
- messageid=f ;;
- -k|--keep)
- keep=t ;;
- --keep-non-patch)
- keep=b ;;
- -c|--scissors)
- scissors=t ;;
- --no-scissors)
- scissors=f ;;
- -r|--resolved|--continue)
- resolved=t ;;
- --skip)
- skip=t ;;
- --abort)
- abort=t ;;
- --rebasing)
- rebasing=t threeway=t ;;
- --resolvemsg=*)
- resolvemsg="${1#--resolvemsg=}" ;;
- --whitespace=*|--directory=*|--exclude=*|--include=*)
- git_apply_opt="$git_apply_opt $(sq "$1")" ;;
- -C*|-p*)
- git_apply_opt="$git_apply_opt $(sq "$1")" ;;
- --patch-format=*)
- patch_format="${1#--patch-format=}" ;;
- --reject|--ignore-whitespace|--ignore-space-change)
- git_apply_opt="$git_apply_opt $1" ;;
- --committer-date-is-author-date)
- committer_date_is_author_date=t ;;
- --ignore-date)
- ignore_date=t ;;
- --rerere-autoupdate|--no-rerere-autoupdate)
- allow_rerere_autoupdate="$1" ;;
- -q|--quiet)
- GIT_QUIET=t ;;
- --keep-cr)
- keepcr=t ;;
- --no-keep-cr)
- keepcr=f ;;
- --gpg-sign)
- gpg_sign_opt=-S ;;
- --gpg-sign=*)
- gpg_sign_opt="-S${1#--gpg-sign=}" ;;
- --)
- shift; break ;;
- *)
- usage ;;
- esac
- shift
-done
-
-# If the dotest directory exists, but we have finished applying all the
-# patches in them, clear it out.
-if test -d "$dotest" &&
- test -f "$dotest/last" &&
- test -f "$dotest/next" &&
- last=$(cat "$dotest/last") &&
- next=$(cat "$dotest/next") &&
- test $# != 0 &&
- test "$next" -gt "$last"
-then
- rm -fr "$dotest"
-fi
-
-if test -d "$dotest" && test -f "$dotest/last" && test -f "$dotest/next"
-then
- case "$#,$skip$resolved$abort" in
- 0,*t*)
- # Explicit resume command and we do not have file, so
- # we are happy.
- : ;;
- 0,)
- # No file input but without resume parameters; catch
- # user error to feed us a patch from standard input
- # when there is already $dotest. This is somewhat
- # unreliable -- stdin could be /dev/null for example
- # and the caller did not intend to feed us a patch but
- # wanted to continue unattended.
- test -t 0
- ;;
- *)
- false
- ;;
- esac ||
- die "$(eval_gettext "previous rebase directory \$dotest still exists but mbox given.")"
- resume=yes
-
- case "$skip,$abort" in
- t,t)
- die "$(gettext "Please make up your mind. --skip or --abort?")"
- ;;
- t,)
- git rerere clear
- head_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree) &&
- git read-tree --reset -u $head_tree $head_tree &&
- index_tree=$(git write-tree) &&
- git read-tree -m -u $index_tree $head_tree
- git read-tree -m $head_tree
- ;;
- ,t)
- if test -f "$dotest/rebasing"
- then
- exec git rebase --abort
- fi
- git rerere clear
- if safe_to_abort
- then
- head_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree) &&
- git read-tree --reset -u $head_tree $head_tree &&
- index_tree=$(git write-tree) &&
- orig_head=$(git rev-parse --verify -q ORIG_HEAD || echo $empty_tree) &&
- git read-tree -m -u $index_tree $orig_head
- if git rev-parse --verify -q ORIG_HEAD >/dev/null 2>&1
- then
- git reset ORIG_HEAD
- else
- git read-tree $empty_tree
- curr_branch=$(git symbolic-ref HEAD 2>/dev/null) &&
- git update-ref -d $curr_branch
- fi
- fi
- rm -fr "$dotest"
- exit ;;
- esac
- rm -f "$dotest/dirtyindex"
-else
- # Possible stray $dotest directory in the independent-run
- # case; in the --rebasing case, it is upto the caller
- # (git-rebase--am) to take care of stray directories.
- if test -d "$dotest" && test -z "$rebasing"
- then
- case "$skip,$resolved,$abort" in
- ,,t)
- rm -fr "$dotest"
- exit 0
- ;;
- *)
- die "$(eval_gettext "Stray \$dotest directory found.
-Use \"git am --abort\" to remove it.")"
- ;;
- esac
- fi
-
- # Make sure we are not given --skip, --continue, or --abort
- test "$skip$resolved$abort" = "" ||
- die "$(gettext "Resolve operation not in progress, we are not resuming.")"
-
- # Start afresh.
- mkdir -p "$dotest" || exit
-
- if test -n "$prefix" && test $# != 0
- then
- first=t
- for arg
- do
- test -n "$first" && {
- set x
- first=
- }
- if is_absolute_path "$arg"
- then
- set "$@" "$arg"
- else
- set "$@" "$prefix$arg"
- fi
- done
- shift
- fi
-
- check_patch_format "$@"
-
- split_patches "$@"
-
- # -i can and must be given when resuming; everything
- # else is kept
- echo " $git_apply_opt" >"$dotest/apply-opt"
- echo "$threeway" >"$dotest/threeway"
- echo "$sign" >"$dotest/sign"
- echo "$utf8" >"$dotest/utf8"
- echo "$keep" >"$dotest/keep"
- echo "$messageid" >"$dotest/messageid"
- echo "$scissors" >"$dotest/scissors"
- echo "$no_inbody_headers" >"$dotest/no_inbody_headers"
- echo "$GIT_QUIET" >"$dotest/quiet"
- echo 1 >"$dotest/next"
- if test -n "$rebasing"
- then
- : >"$dotest/rebasing"
- else
- : >"$dotest/applying"
- if test -n "$HAS_HEAD"
- then
- git update-ref ORIG_HEAD HEAD
- else
- git update-ref -d ORIG_HEAD >/dev/null 2>&1
- fi
- fi
-fi
-
-git update-index -q --refresh
-
-case "$resolved" in
-'')
- case "$HAS_HEAD" in
- '')
- files=$(git ls-files) ;;
- ?*)
- files=$(git diff-index --cached --name-only HEAD --) ;;
- esac || exit
- if test "$files"
- then
- test -n "$HAS_HEAD" && : >"$dotest/dirtyindex"
- die "$(eval_gettext "Dirty index: cannot apply patches (dirty: \$files)")"
- fi
-esac
-
-# Now, decide what command line options we will give to the git
-# commands we invoke, based on the result of parsing command line
-# options and previous invocation state stored in $dotest/ files.
-
-if test "$(cat "$dotest/utf8")" = t
-then
- utf8=-u
-else
- utf8=-n
-fi
-keep=$(cat "$dotest/keep")
-case "$keep" in
-t)
- keep=-k ;;
-b)
- keep=-b ;;
-*)
- keep= ;;
-esac
-case "$(cat "$dotest/messageid")" in
-t)
- messageid=-m ;;
-f)
- messageid= ;;
-esac
-case "$(cat "$dotest/scissors")" in
-t)
- scissors=--scissors ;;
-f)
- scissors=--no-scissors ;;
-esac
-if test "$(cat "$dotest/no_inbody_headers")" = t
-then
- no_inbody_headers=--no-inbody-headers
-else
- no_inbody_headers=
-fi
-if test "$(cat "$dotest/quiet")" = t
-then
- GIT_QUIET=t
-fi
-if test "$(cat "$dotest/threeway")" = t
-then
- threeway=t
-fi
-git_apply_opt=$(cat "$dotest/apply-opt")
-if test "$(cat "$dotest/sign")" = t
-then
- SIGNOFF=$(git var GIT_COMMITTER_IDENT | sed -e '
- s/>.*/>/
- s/^/Signed-off-by: /'
- )
-else
- SIGNOFF=
-fi
-
-last=$(cat "$dotest/last")
-this=$(cat "$dotest/next")
-if test "$skip" = t
-then
- this=$(expr "$this" + 1)
- resume=
-fi
-
-while test "$this" -le "$last"
-do
- msgnum=$(printf "%0${prec}d" $this)
- next=$(expr "$this" + 1)
- test -f "$dotest/$msgnum" || {
- resume=
- go_next
- continue
- }
-
- # If we are not resuming, parse and extract the patch information
- # into separate files:
- # - info records the authorship and title
- # - msg is the rest of commit log message
- # - patch is the patch body.
- #
- # When we are resuming, these files are either already prepared
- # by the user, or the user can tell us to do so by --continue flag.
- case "$resume" in
- '')
- if test -f "$dotest/rebasing"
- then
- commit=$(sed -e 's/^From \([0-9a-f]*\) .*/\1/' \
- -e q "$dotest/$msgnum") &&
- test "$(git cat-file -t "$commit")" = commit ||
- stop_here $this
- git cat-file commit "$commit" |
- sed -e '1,/^$/d' >"$dotest/msg-clean"
- echo "$commit" >"$dotest/original-commit"
- get_author_ident_from_commit "$commit" >"$dotest/author-script"
- git diff-tree --root --binary --full-index "$commit" >"$dotest/patch"
- else
- git mailinfo $keep $no_inbody_headers $messageid $scissors $utf8 "$dotest/msg" "$dotest/patch" \
- <"$dotest/$msgnum" >"$dotest/info" ||
- stop_here $this
-
- # skip pine's internal folder data
- sane_grep '^Author: Mail System Internal Data$' \
- <"$dotest"/info >/dev/null &&
- go_next && continue
-
- test -s "$dotest/patch" || {
- eval_gettextln "Patch is empty. Was it split wrong?
-If you would prefer to skip this patch, instead run \"\$cmdline --skip\".
-To restore the original branch and stop patching run \"\$cmdline --abort\"."
- stop_here $this
- }
- rm -f "$dotest/original-commit" "$dotest/author-script"
- {
- sed -n '/^Subject/ s/Subject: //p' "$dotest/info"
- echo
- cat "$dotest/msg"
- } |
- git stripspace > "$dotest/msg-clean"
- fi
- ;;
- esac
-
- if test -f "$dotest/author-script"
- then
- eval $(cat "$dotest/author-script")
- else
- GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$dotest/info")"
- GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")"
- GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")"
- fi
-
- if test -z "$GIT_AUTHOR_EMAIL"
- then
- gettextln "Patch does not have a valid e-mail address."
- stop_here $this
- fi
-
- export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
-
- case "$resume" in
- '')
- if test '' != "$SIGNOFF"
- then
- LAST_SIGNED_OFF_BY=$(
- sed -ne '/^Signed-off-by: /p' \
- "$dotest/msg-clean" |
- sed -ne '$p'
- )
- ADD_SIGNOFF=$(
- test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
- test '' = "$LAST_SIGNED_OFF_BY" && echo
- echo "$SIGNOFF"
- })
- else
- ADD_SIGNOFF=
- fi
- {
- if test -s "$dotest/msg-clean"
- then
- cat "$dotest/msg-clean"
- fi
- if test '' != "$ADD_SIGNOFF"
- then
- echo "$ADD_SIGNOFF"
- fi
- } >"$dotest/final-commit"
- ;;
- *)
- case "$resolved$interactive" in
- tt)
- # This is used only for interactive view option.
- git diff-index -p --cached HEAD -- >"$dotest/patch"
- ;;
- esac
- esac
-
- resume=
- if test "$interactive" = t
- then
- test -t 0 ||
- die "$(gettext "cannot be interactive without stdin connected to a terminal.")"
- action=again
- while test "$action" = again
- do
- gettextln "Commit Body is:"
- echo "--------------------------"
- cat "$dotest/final-commit"
- echo "--------------------------"
- # TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
- # in your translation. The program will only accept English
- # input at this point.
- gettext "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
- read reply
- case "$reply" in
- [yY]*) action=yes ;;
- [aA]*) action=yes interactive= ;;
- [nN]*) action=skip ;;
- [eE]*) git_editor "$dotest/final-commit"
- action=again ;;
- [vV]*) action=again
- git_pager "$dotest/patch" ;;
- *) action=again ;;
- esac
- done
- else
- action=yes
- fi
-
- if test $action = skip
- then
- go_next
- continue
- fi
-
- hook="$(git rev-parse --git-path hooks/applypatch-msg)"
- if test -x "$hook"
- then
- "$hook" "$dotest/final-commit" || stop_here $this
- fi
-
- if test -f "$dotest/final-commit"
- then
- FIRSTLINE=$(sed 1q "$dotest/final-commit")
- else
- FIRSTLINE=""
- fi
-
- say "$(eval_gettext "Applying: \$FIRSTLINE")"
-
- case "$resolved" in
- '')
- # When we are allowed to fall back to 3-way later, don't give
- # false errors during the initial attempt.
- squelch=
- if test "$threeway" = t
- then
- squelch='>/dev/null 2>&1 '
- fi
- eval "git apply $squelch$git_apply_opt"' --index "$dotest/patch"'
- apply_status=$?
- ;;
- t)
- # Resolved means the user did all the hard work, and
- # we do not have to do any patch application. Just
- # trust what the user has in the index file and the
- # working tree.
- resolved=
- git diff-index --quiet --cached HEAD -- && {
- gettextln "No changes - did you forget to use 'git add'?
-If there is nothing left to stage, chances are that something else
-already introduced the same changes; you might want to skip this patch."
- stop_here_user_resolve $this
- }
- unmerged=$(git ls-files -u)
- if test -n "$unmerged"
- then
- gettextln "You still have unmerged paths in your index
-did you forget to use 'git add'?"
- stop_here_user_resolve $this
- fi
- apply_status=0
- git rerere
- ;;
- esac
-
- if test $apply_status != 0 && test "$threeway" = t
- then
- if (fall_back_3way)
- then
- # Applying the patch to an earlier tree and merging the
- # result may have produced the same tree as ours.
- git diff-index --quiet --cached HEAD -- && {
- say "$(gettext "No changes -- Patch already applied.")"
- go_next
- continue
- }
- # clear apply_status -- we have successfully merged.
- apply_status=0
- fi
- fi
- if test $apply_status != 0
- then
- eval_gettextln 'Patch failed at $msgnum $FIRSTLINE'
- if test "$(git config --bool advice.amworkdir)" != false
- then
- eval_gettextln 'The copy of the patch that failed is found in:
- $dotest/patch'
- fi
- stop_here_user_resolve $this
- fi
-
- hook="$(git rev-parse --git-path hooks/pre-applypatch)"
- if test -x "$hook"
- then
- "$hook" || stop_here $this
- fi
-
- tree=$(git write-tree) &&
- commit=$(
- if test -n "$ignore_date"
- then
- GIT_AUTHOR_DATE=
- fi
- parent=$(git rev-parse --verify -q HEAD) ||
- say >&2 "$(gettext "applying to an empty history")"
-
- if test -n "$committer_date_is_author_date"
- then
- GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
- export GIT_COMMITTER_DATE
- fi &&
- git commit-tree ${parent:+-p} $parent ${gpg_sign_opt:+"$gpg_sign_opt"} $tree \
- <"$dotest/final-commit"
- ) &&
- git update-ref -m "$GIT_REFLOG_ACTION: $FIRSTLINE" HEAD $commit $parent ||
- stop_here $this
-
- if test -f "$dotest/original-commit"; then
- echo "$(cat "$dotest/original-commit") $commit" >> "$dotest/rewritten"
- fi
-
- hook="$(git rev-parse --git-path hooks/post-applypatch)"
- test -x "$hook" && "$hook"
-
- go_next
-done
-
-if test -s "$dotest"/rewritten; then
- git notes copy --for-rewrite=rebase < "$dotest"/rewritten
- hook="$(git rev-parse --git-path hooks/post-rewrite)"
- if test -x "$hook"; then
- "$hook" rebase < "$dotest"/rewritten
- fi
-fi
-
-# If am was called with --rebasing (from git-rebase--am), it's up to
-# the caller to take care of housekeeping.
-if ! test -f "$dotest/rebasing"
-then
- rm -fr "$dotest"
- git gc --auto
-fi
+++ /dev/null
-#!/bin/sh
-
-OPTIONS_KEEPDASHDASH=t
-OPTIONS_SPEC="\
-git-checkout [options] [<branch>] [<paths>...]
---
-b= create a new branch started at <branch>
-l create the new branch's reflog
-track arrange that the new branch tracks the remote branch
-f proceed even if the index or working tree is not HEAD
-m merge local modifications into the new branch
-q,quiet be quiet
-"
-SUBDIRECTORY_OK=Sometimes
-. git-sh-setup
-require_work_tree
-
-old_name=HEAD
-old=$(git rev-parse --verify $old_name 2>/dev/null)
-oldbranch=$(git symbolic-ref $old_name 2>/dev/null)
-new=
-new_name=
-force=
-branch=
-track=
-newbranch=
-newbranch_log=
-merge=
-quiet=
-v=-v
-LF='
-'
-
-while test $# != 0; do
- case "$1" in
- -b)
- shift
- newbranch="$1"
- [ -z "$newbranch" ] &&
- die "git checkout: -b needs a branch name"
- git show-ref --verify --quiet -- "refs/heads/$newbranch" &&
- die "git checkout: branch $newbranch already exists"
- git check-ref-format "heads/$newbranch" ||
- die "git checkout: we do not like '$newbranch' as a branch name."
- ;;
- -l)
- newbranch_log=-l
- ;;
- --track|--no-track)
- track="$1"
- ;;
- -f)
- force=1
- ;;
- -m)
- merge=1
- ;;
- -q|--quiet)
- quiet=1
- v=
- ;;
- --)
- shift
- break
- ;;
- *)
- usage
- ;;
- esac
- shift
-done
-
-arg="$1"
-rev=$(git rev-parse --verify "$arg" 2>/dev/null)
-if rev=$(git rev-parse --verify "$rev^0" 2>/dev/null)
-then
- [ -z "$rev" ] && die "unknown flag $arg"
- new_name="$arg"
- if git show-ref --verify --quiet -- "refs/heads/$arg"
- then
- rev=$(git rev-parse --verify "refs/heads/$arg^0")
- branch="$arg"
- fi
- new="$rev"
- shift
-elif rev=$(git rev-parse --verify "$rev^{tree}" 2>/dev/null)
-then
- # checking out selected paths from a tree-ish.
- new="$rev"
- new_name="$rev^{tree}"
- shift
-fi
-[ "$1" = "--" ] && shift
-
-case "$newbranch,$track" in
-,--*)
- die "git checkout: --track and --no-track require -b"
-esac
-
-case "$force$merge" in
-11)
- die "git checkout: -f and -m are incompatible"
-esac
-
-# The behaviour of the command with and without explicit path
-# parameters is quite different.
-#
-# Without paths, we are checking out everything in the work tree,
-# possibly switching branches. This is the traditional behaviour.
-#
-# With paths, we are _never_ switching branch, but checking out
-# the named paths from either index (when no rev is given),
-# or the named tree-ish (when rev is given).
-
-if test "$#" -ge 1
-then
- hint=
- if test "$#" -eq 1
- then
- hint="
-Did you intend to checkout '$@' which can not be resolved as commit?"
- fi
- if test '' != "$newbranch$force$merge"
- then
- die "git checkout: updating paths is incompatible with switching branches/forcing$hint"
- fi
- if test '' != "$new"
- then
- # from a specific tree-ish; note that this is for
- # rescuing paths and is never meant to remove what
- # is not in the named tree-ish.
- git ls-tree --full-name -r "$new" "$@" |
- git update-index --index-info || exit $?
- fi
-
- # Make sure the request is about existing paths.
- git ls-files --full-name --error-unmatch -- "$@" >/dev/null || exit
- git ls-files --full-name -- "$@" |
- (cd_to_toplevel && git checkout-index -f -u --stdin)
-
- # Run a post-checkout hook -- the HEAD does not change so the
- # current HEAD is passed in for both args
- if test -x "$GIT_DIR"/hooks/post-checkout; then
- "$GIT_DIR"/hooks/post-checkout $old $old 0
- fi
-
- exit $?
-else
- # Make sure we did not fall back on $arg^{tree} codepath
- # since we are not checking out from an arbitrary tree-ish,
- # but switching branches.
- if test '' != "$new"
- then
- git rev-parse --verify "$new^{commit}" >/dev/null 2>&1 ||
- die "Cannot switch branch to a non-commit."
- fi
-fi
-
-# We are switching branches and checking out trees, so
-# we *NEED* to be at the toplevel.
-cd_to_toplevel
-
-[ -z "$new" ] && new=$old && new_name="$old_name"
-
-# If we don't have an existing branch that we're switching to,
-# and we don't have a new branch name for the target we
-# are switching to, then we are detaching our HEAD from any
-# branch. However, if "git checkout HEAD" detaches the HEAD
-# from the current branch, even though that may be logically
-# correct, it feels somewhat funny. More importantly, we do not
-# want "git checkout" or "git checkout -f" to detach HEAD.
-
-detached=
-detach_warn=
-
-describe_detached_head () {
- test -n "$quiet" || {
- printf >&2 "$1 "
- GIT_PAGER= git log >&2 -1 --pretty=oneline --abbrev-commit "$2" --
- }
-}
-
-if test -z "$branch$newbranch" && test "$new_name" != "$old_name"
-then
- detached="$new"
- if test -n "$oldbranch" && test -z "$quiet"
- then
- detach_warn="Note: moving to \"$new_name\" which isn't a local branch
-If you want to create a new branch from this checkout, you may do so
-(now or later) by using -b with the checkout command again. Example:
- git checkout -b <new_branch_name>"
- fi
-elif test -z "$oldbranch" && test "$new" != "$old"
-then
- describe_detached_head 'Previous HEAD position was' "$old"
-fi
-
-if [ "X$old" = X ]
-then
- if test -z "$quiet"
- then
- echo >&2 "warning: You appear to be on a branch yet to be born."
- echo >&2 "warning: Forcing checkout of $new_name."
- fi
- force=1
-fi
-
-if [ "$force" ]
-then
- git read-tree $v --reset -u $new
-else
- git update-index --refresh >/dev/null
- git read-tree $v -m -u --exclude-per-directory=.gitignore $old $new || (
- case "$merge,$v" in
- ,*)
- exit 1 ;;
- 1,)
- ;; # quiet
- *)
- echo >&2 "Falling back to 3-way merge..." ;;
- esac
-
- # Match the index to the working tree, and do a three-way.
- git diff-files --name-only | git update-index --remove --stdin &&
- work=$(git write-tree) &&
- git read-tree $v --reset -u $new || exit
-
- eval GITHEAD_$new='${new_name:-${branch:-$new}}' &&
- eval GITHEAD_$work=local &&
- export GITHEAD_$new GITHEAD_$work &&
- git merge-recursive $old -- $new $work
-
- # Do not register the cleanly merged paths in the index yet.
- # this is not a real merge before committing, but just carrying
- # the working tree changes along.
- unmerged=$(git ls-files -u)
- git read-tree $v --reset $new
- case "$unmerged" in
- '') ;;
- *)
- (
- z40=0000000000000000000000000000000000000000
- echo "$unmerged" |
- sed -e 's/^[0-7]* [0-9a-f]* /'"0 $z40 /"
- echo "$unmerged"
- ) | git update-index --index-info
- ;;
- esac
- exit 0
- )
- saved_err=$?
- if test "$saved_err" = 0 && test -z "$quiet"
- then
- git diff-index --name-status "$new"
- fi
- (exit $saved_err)
-fi
-
-#
-# Switch the HEAD pointer to the new branch if we
-# checked out a branch head, and remove any potential
-# old MERGE_HEAD's (subsequent commits will clearly not
-# be based on them, since we re-set the index)
-#
-if [ "$?" -eq 0 ]; then
- if [ "$newbranch" ]; then
- git branch $track $newbranch_log "$newbranch" "$new_name" || exit
- branch="$newbranch"
- fi
- if test -n "$branch"
- then
- old_branch_name=$(expr "z$oldbranch" : 'zrefs/heads/\(.*\)')
- GIT_DIR="$GIT_DIR" git symbolic-ref -m "checkout: moving from ${old_branch_name:-$old} to $branch" HEAD "refs/heads/$branch"
- if test -n "$quiet"
- then
- true # nothing
- elif test "refs/heads/$branch" = "$oldbranch"
- then
- echo >&2 "Already on branch \"$branch\""
- else
- echo >&2 "Switched to${newbranch:+ a new} branch \"$branch\""
- fi
- elif test -n "$detached"
- then
- old_branch_name=$(expr "z$oldbranch" : 'zrefs/heads/\(.*\)')
- git update-ref --no-deref -m "checkout: moving from ${old_branch_name:-$old} to $arg" HEAD "$detached" ||
- die "Cannot detach HEAD"
- if test -n "$detach_warn"
- then
- echo >&2 "$detach_warn"
- fi
- describe_detached_head 'HEAD is now at' HEAD
- fi
- rm -f "$GIT_DIR/MERGE_HEAD"
-else
- exit 1
-fi
-
-# Run a post-checkout hook
-if test -x "$GIT_DIR"/hooks/post-checkout; then
- "$GIT_DIR"/hooks/post-checkout $old $new 1
-fi
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005-2006 Pavel Roskin
-#
-
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC="\
-git-clean [options] <paths>...
-
-Clean untracked files from the working directory
-
-When optional <paths>... arguments are given, the paths
-affected are further limited to those that match them.
---
-d remove directories as well
-f override clean.requireForce and clean anyway
-n don't remove anything, just show what would be done
-q be quiet, only report errors
-x remove ignored files as well
-X remove only ignored files"
-
-SUBDIRECTORY_OK=Yes
-. git-sh-setup
-require_work_tree
-
-ignored=
-ignoredonly=
-cleandir=
-rmf="rm -f --"
-rmrf="rm -rf --"
-rm_refuse="echo Not removing"
-echo1="echo"
-
-disabled=$(git config --bool clean.requireForce)
-
-while test $# != 0
-do
- case "$1" in
- -d)
- cleandir=1
- ;;
- -f)
- disabled=false
- ;;
- -n)
- disabled=false
- rmf="echo Would remove"
- rmrf="echo Would remove"
- rm_refuse="echo Would not remove"
- echo1=":"
- ;;
- -q)
- echo1=":"
- ;;
- -x)
- ignored=1
- ;;
- -X)
- ignoredonly=1
- ;;
- --)
- shift
- break
- ;;
- *)
- usage # should not happen
- ;;
- esac
- shift
-done
-
-# requireForce used to default to false but now it defaults to true.
-# IOW, lack of explicit "clean.requireForce = false" is taken as
-# "clean.requireForce = true".
-case "$disabled" in
-"")
- die "clean.requireForce not set and -n or -f not given; refusing to clean"
- ;;
-"true")
- die "clean.requireForce set and -n or -f not given; refusing to clean"
- ;;
-esac
-
-if [ "$ignored,$ignoredonly" = "1,1" ]; then
- die "-x and -X cannot be set together"
-fi
-
-if [ -z "$ignored" ]; then
- excl="--exclude-per-directory=.gitignore"
- excl_info= excludes_file=
- if [ -f "$GIT_DIR/info/exclude" ]; then
- excl_info="--exclude-from=$GIT_DIR/info/exclude"
- fi
- if cfg_excl=$(git config core.excludesfile) && test -f "$cfg_excl"
- then
- excludes_file="--exclude-from=$cfg_excl"
- fi
- if [ "$ignoredonly" ]; then
- excl="$excl --ignored"
- fi
-fi
-
-git ls-files --others --directory \
- $excl ${excl_info:+"$excl_info"} ${excludes_file:+"$excludes_file"} \
- -- "$@" |
-while read -r file; do
- if [ -d "$file" -a ! -L "$file" ]; then
- if [ -z "$cleandir" ]; then
- $rm_refuse "$file"
- continue
- fi
- $echo1 "Removing $file"
- $rmrf "$file"
- else
- $echo1 "Removing $file"
- $rmf "$file"
- fi
-done
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005, Linus Torvalds
-# Copyright (c) 2005, Junio C Hamano
-#
-# Clone a repository into a different directory that does not yet exist.
-
-# See git-sh-setup why.
-unset CDPATH
-
-OPTIONS_SPEC="\
-git-clone [options] [--] <repo> [<dir>]
---
-n,no-checkout don't create a checkout
-bare create a bare repository
-naked create a bare repository
-l,local to clone from a local repository
-no-hardlinks don't use local hardlinks, always copy
-s,shared setup as a shared repository
-template= path to the template directory
-q,quiet be quiet
-reference= reference repository
-o,origin= use <name> instead of 'origin' to track upstream
-u,upload-pack= path to git-upload-pack on the remote
-depth= create a shallow clone of that depth
-
-use-separate-remote compatibility, do not use
-no-separate-remote compatibility, do not use"
-
-die() {
- echo >&2 "$@"
- exit 1
-}
-
-usage() {
- exec "$0" -h
-}
-
-eval "$(echo "$OPTIONS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
-
-get_repo_base() {
- (
- cd "$(/bin/pwd)" &&
- cd "$1" || cd "$1.git" &&
- {
- cd .git
- pwd
- }
- ) 2>/dev/null
-}
-
-if [ -n "$GIT_SSL_NO_VERIFY" -o \
- "$(git config --bool http.sslVerify)" = false ]; then
- curl_extra_args="-k"
-fi
-
-http_fetch () {
- # $1 = Remote, $2 = Local
- curl -nsfL $curl_extra_args "$1" >"$2"
- curl_exit_status=$?
- case $curl_exit_status in
- 126|127) exit ;;
- *) return $curl_exit_status ;;
- esac
-}
-
-clone_dumb_http () {
- # $1 - remote, $2 - local
- cd "$2" &&
- clone_tmp="$GIT_DIR/clone-tmp" &&
- mkdir -p "$clone_tmp" || exit 1
- if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
- "$(git config --bool http.noEPSV)" = true ]; then
- curl_extra_args="${curl_extra_args} --disable-epsv"
- fi
- http_fetch "$1/info/refs" "$clone_tmp/refs" ||
- die "Cannot get remote repository information.
-Perhaps git-update-server-info needs to be run there?"
- test "z$quiet" = z && v=-v || v=
- while read sha1 refname
- do
- name=$(expr "z$refname" : 'zrefs/\(.*\)') &&
- case "$name" in
- *^*) continue;;
- esac
- case "$bare,$name" in
- yes,* | ,heads/* | ,tags/*) ;;
- *) continue ;;
- esac
- if test -n "$use_separate_remote" &&
- branch_name=$(expr "z$name" : 'zheads/\(.*\)')
- then
- tname="remotes/$origin/$branch_name"
- else
- tname=$name
- fi
- git-http-fetch $v -a -w "$tname" "$sha1" "$1" || exit 1
- done <"$clone_tmp/refs"
- rm -fr "$clone_tmp"
- http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" ||
- rm -f "$GIT_DIR/REMOTE_HEAD"
- if test -f "$GIT_DIR/REMOTE_HEAD"; then
- head_sha1=$(cat "$GIT_DIR/REMOTE_HEAD")
- case "$head_sha1" in
- 'ref: refs/'*)
- ;;
- *)
- git-http-fetch $v -a "$head_sha1" "$1" ||
- rm -f "$GIT_DIR/REMOTE_HEAD"
- ;;
- esac
- fi
-}
-
-quiet=
-local=no
-use_local_hardlink=yes
-local_shared=no
-unset template
-no_checkout=
-upload_pack=
-bare=
-reference=
-origin=
-origin_override=
-use_separate_remote=t
-depth=
-no_progress=
-local_explicitly_asked_for=
-test -t 1 || no_progress=--no-progress
-
-while test $# != 0
-do
- case "$1" in
- -n|--no-checkout)
- no_checkout=yes ;;
- --naked|--bare)
- bare=yes ;;
- -l|--local)
- local_explicitly_asked_for=yes
- use_local_hardlink=yes
- ;;
- --no-hardlinks)
- use_local_hardlink=no ;;
- -s|--shared)
- local_shared=yes ;;
- --template)
- shift; template="--template=$1" ;;
- -q|--quiet)
- quiet=-q ;;
- --use-separate-remote|--no-separate-remote)
- die "clones are always made with separate-remote layout" ;;
- --reference)
- shift; reference="$1" ;;
- -o|--origin)
- shift;
- case "$1" in
- '')
- usage ;;
- */*)
- die "'$1' is not suitable for an origin name"
- esac
- git check-ref-format "heads/$1" ||
- die "'$1' is not suitable for a branch name"
- test -z "$origin_override" ||
- die "Do not give more than one --origin options."
- origin_override=yes
- origin="$1"
- ;;
- -u|--upload-pack)
- shift
- upload_pack="--upload-pack=$1" ;;
- --depth)
- shift
- depth="--depth=$1" ;;
- --)
- shift
- break ;;
- *)
- usage ;;
- esac
- shift
-done
-
-repo="$1"
-test -n "$repo" ||
- die 'you must specify a repository to clone.'
-
-# --bare implies --no-checkout and --no-separate-remote
-if test yes = "$bare"
-then
- if test yes = "$origin_override"
- then
- die '--bare and --origin $origin options are incompatible.'
- fi
- no_checkout=yes
- use_separate_remote=
-fi
-
-if test -z "$origin"
-then
- origin=origin
-fi
-
-# Turn the source into an absolute path if
-# it is local
-if base=$(get_repo_base "$repo"); then
- repo="$base"
- if test -z "$depth"
- then
- local=yes
- fi
-elif test -f "$repo"
-then
- case "$repo" in /*) ;; *) repo="$PWD/$repo" ;; esac
-fi
-
-# Decide the directory name of the new repository
-if test -n "$2"
-then
- dir="$2"
- test $# = 2 || die "excess parameter to git-clone"
-else
- # Derive one from the repository name
- # Try using "humanish" part of source repo if user didn't specify one
- if test -f "$repo"
- then
- # Cloning from a bundle
- dir=$(echo "$repo" | sed -e 's|/*\.bundle$||' -e 's|.*/||g')
- else
- dir=$(echo "$repo" |
- sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
- fi
-fi
-
-[ -e "$dir" ] && die "destination directory '$dir' already exists."
-[ yes = "$bare" ] && unset GIT_WORK_TREE
-[ -n "$GIT_WORK_TREE" ] && [ -e "$GIT_WORK_TREE" ] &&
-die "working tree '$GIT_WORK_TREE' already exists."
-D=
-W=
-cleanup() {
- test -z "$D" && rm -rf "$dir"
- test -z "$W" && test -n "$GIT_WORK_TREE" && rm -rf "$GIT_WORK_TREE"
- cd ..
- test -n "$D" && rm -rf "$D"
- test -n "$W" && rm -rf "$W"
- exit $err
-}
-trap 'err=$?; cleanup' 0
-mkdir -p "$dir" && D=$(cd "$dir" && pwd) || usage
-test -n "$GIT_WORK_TREE" && mkdir -p "$GIT_WORK_TREE" &&
-W=$(cd "$GIT_WORK_TREE" && pwd) && GIT_WORK_TREE="$W" && export GIT_WORK_TREE
-if test yes = "$bare" || test -n "$GIT_WORK_TREE"; then
- GIT_DIR="$D"
-else
- GIT_DIR="$D/.git"
-fi &&
-export GIT_DIR &&
-GIT_CONFIG="$GIT_DIR/config" git-init $quiet ${template+"$template"} || usage
-
-if test -n "$bare"
-then
- GIT_CONFIG="$GIT_DIR/config" git config core.bare true
-fi
-
-if test -n "$reference"
-then
- ref_git=
- if test -d "$reference"
- then
- if test -d "$reference/.git/objects"
- then
- ref_git="$reference/.git"
- elif test -d "$reference/objects"
- then
- ref_git="$reference"
- fi
- fi
- if test -n "$ref_git"
- then
- ref_git=$(cd "$ref_git" && pwd)
- echo "$ref_git/objects" >"$GIT_DIR/objects/info/alternates"
- (
- GIT_DIR="$ref_git" git for-each-ref \
- --format='%(objectname) %(*objectname)'
- ) |
- while read a b
- do
- test -z "$a" ||
- git update-ref "refs/reference-tmp/$a" "$a"
- test -z "$b" ||
- git update-ref "refs/reference-tmp/$b" "$b"
- done
- else
- die "reference repository '$reference' is not a local directory."
- fi
-fi
-
-rm -f "$GIT_DIR/CLONE_HEAD"
-
-# We do local magic only when the user tells us to.
-case "$local" in
-yes)
- ( cd "$repo/objects" ) ||
- die "cannot chdir to local '$repo/objects'."
-
- if test "$local_shared" = yes
- then
- mkdir -p "$GIT_DIR/objects/info"
- echo "$repo/objects" >>"$GIT_DIR/objects/info/alternates"
- else
- cpio_quiet_flag=""
- cpio --help 2>&1 | grep -- --quiet >/dev/null && \
- cpio_quiet_flag=--quiet
- l= &&
- if test "$use_local_hardlink" = yes
- then
- # See if we can hardlink and drop "l" if not.
- sample_file=$(cd "$repo" && \
- find objects -type f -print | sed -e 1q)
- # objects directory should not be empty because
- # we are cloning!
- test -f "$repo/$sample_file" ||
- die "fatal: cannot clone empty repository"
- if ln "$repo/$sample_file" "$GIT_DIR/objects/sample" 2>/dev/null
- then
- rm -f "$GIT_DIR/objects/sample"
- l=l
- elif test -n "$local_explicitly_asked_for"
- then
- echo >&2 "Warning: -l asked but cannot hardlink to $repo"
- fi
- fi &&
- cd "$repo" &&
- # Create dirs using umask and permissions and destination
- find objects -type d -print | (cd "$GIT_DIR" && xargs mkdir -p) &&
- # Copy existing 0444 permissions on content
- find objects ! -type d -print | cpio $cpio_quiet_flag -pumd$l "$GIT_DIR/" || \
- exit 1
- fi
- git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
- ;;
-*)
- case "$repo" in
- rsync://*)
- case "$depth" in
- "") ;;
- *) die "shallow over rsync not supported" ;;
- esac
- rsync $quiet -av --ignore-existing \
- --exclude info "$repo/objects/" "$GIT_DIR/objects/" ||
- exit
- # Look at objects/info/alternates for rsync -- http will
- # support it natively and git native ones will do it on the
- # remote end. Not having that file is not a crime.
- rsync -q "$repo/objects/info/alternates" \
- "$GIT_DIR/TMP_ALT" 2>/dev/null ||
- rm -f "$GIT_DIR/TMP_ALT"
- if test -f "$GIT_DIR/TMP_ALT"
- then
- ( cd "$D" &&
- . git-parse-remote &&
- resolve_alternates "$repo" <"$GIT_DIR/TMP_ALT" ) |
- while read alt
- do
- case "$alt" in 'bad alternate: '*) die "$alt";; esac
- case "$quiet" in
- '') echo >&2 "Getting alternate: $alt" ;;
- esac
- rsync $quiet -av --ignore-existing \
- --exclude info "$alt" "$GIT_DIR/objects" || exit
- done
- rm -f "$GIT_DIR/TMP_ALT"
- fi
- git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
- ;;
- https://*|http://*|ftp://*)
- case "$depth" in
- "") ;;
- *) die "shallow over http or ftp not supported" ;;
- esac
- if test -z "@@NO_CURL@@"
- then
- clone_dumb_http "$repo" "$D"
- else
- die "http transport not supported, rebuild Git with curl support"
- fi
- ;;
- *)
- if [ -f "$repo" ] ; then
- git bundle unbundle "$repo" > "$GIT_DIR/CLONE_HEAD" ||
- die "unbundle from '$repo' failed."
- else
- case "$upload_pack" in
- '') git-fetch-pack --all -k $quiet $depth $no_progress "$repo";;
- *) git-fetch-pack --all -k \
- $quiet "$upload_pack" $depth $no_progress "$repo" ;;
- esac >"$GIT_DIR/CLONE_HEAD" ||
- die "fetch-pack from '$repo' failed."
- fi
- ;;
- esac
- ;;
-esac
-test -d "$GIT_DIR/refs/reference-tmp" && rm -fr "$GIT_DIR/refs/reference-tmp"
-
-if test -f "$GIT_DIR/CLONE_HEAD"
-then
- # Read git-fetch-pack -k output and store the remote branches.
- if [ -n "$use_separate_remote" ]
- then
- branch_top="remotes/$origin"
- else
- branch_top="heads"
- fi
- tag_top="tags"
- while read sha1 name
- do
- case "$name" in
- *'^{}')
- continue ;;
- HEAD)
- destname="REMOTE_HEAD" ;;
- refs/heads/*)
- destname="refs/$branch_top/${name#refs/heads/}" ;;
- refs/tags/*)
- destname="refs/$tag_top/${name#refs/tags/}" ;;
- *)
- continue ;;
- esac
- git update-ref -m "clone: from $repo" "$destname" "$sha1" ""
- done < "$GIT_DIR/CLONE_HEAD"
-fi
-
-if test -n "$W"; then
- cd "$W" || exit
-else
- cd "$D" || exit
-fi
-
-if test -z "$bare"
-then
- # a non-bare repository is always in separate-remote layout
- remote_top="refs/remotes/$origin"
- head_sha1=
- test ! -r "$GIT_DIR/REMOTE_HEAD" || head_sha1=$(cat "$GIT_DIR/REMOTE_HEAD")
- case "$head_sha1" in
- 'ref: refs/'*)
- # Uh-oh, the remote told us (http transport done against
- # new style repository with a symref HEAD).
- # Ideally we should skip the guesswork but for now
- # opt for minimum change.
- head_sha1=$(expr "z$head_sha1" : 'zref: refs/heads/\(.*\)')
- head_sha1=$(cat "$GIT_DIR/$remote_top/$head_sha1")
- ;;
- esac
-
- # The name under $remote_top the remote HEAD seems to point at.
- head_points_at=$(
- (
- test -f "$GIT_DIR/$remote_top/master" && echo "master"
- cd "$GIT_DIR/$remote_top" &&
- find . -type f -print | sed -e 's/^\.\///'
- ) | (
- done=f
- while read name
- do
- test t = $done && continue
- branch_tip=$(cat "$GIT_DIR/$remote_top/$name")
- if test "$head_sha1" = "$branch_tip"
- then
- echo "$name"
- done=t
- fi
- done
- )
- )
-
- # Upstream URL
- git config remote."$origin".url "$repo" &&
-
- # Set up the mappings to track the remote branches.
- git config remote."$origin".fetch \
- "+refs/heads/*:$remote_top/*" '^$' &&
-
- # Write out remote.$origin config, and update our "$head_points_at".
- case "$head_points_at" in
- ?*)
- # Local default branch
- git symbolic-ref HEAD "refs/heads/$head_points_at" &&
-
- # Tracking branch for the primary branch at the remote.
- git update-ref HEAD "$head_sha1" &&
-
- rm -f "refs/remotes/$origin/HEAD"
- git symbolic-ref "refs/remotes/$origin/HEAD" \
- "refs/remotes/$origin/$head_points_at" &&
-
- git config branch."$head_points_at".remote "$origin" &&
- git config branch."$head_points_at".merge "refs/heads/$head_points_at"
- ;;
- '')
- if test -z "$head_sha1"
- then
- # Source had nonexistent ref in HEAD
- echo >&2 "Warning: Remote HEAD refers to nonexistent ref, unable to checkout."
- no_checkout=t
- else
- # Source had detached HEAD pointing nowhere
- git update-ref --no-deref HEAD "$head_sha1" &&
- rm -f "refs/remotes/$origin/HEAD"
- fi
- ;;
- esac
-
- case "$no_checkout" in
- '')
- test "z$quiet" = z && test "z$no_progress" = z && v=-v || v=
- git read-tree -m -u $v HEAD HEAD
- esac
-fi
-rm -f "$GIT_DIR/CLONE_HEAD" "$GIT_DIR/REMOTE_HEAD"
-
-trap - 0
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-# Copyright (c) 2006 Junio C Hamano
-
-USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]'
-SUBDIRECTORY_OK=Yes
-OPTIONS_SPEC=
-. git-sh-setup
-require_work_tree
-
-git rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t
-
-case "$0" in
-*status)
- status_only=t
- ;;
-*commit)
- status_only=
- ;;
-esac
-
-refuse_partial () {
- echo >&2 "$1"
- echo >&2 "You might have meant to say 'git commit -i paths...', perhaps?"
- exit 1
-}
-
-TMP_INDEX=
-THIS_INDEX="${GIT_INDEX_FILE:-$GIT_DIR/index}"
-NEXT_INDEX="$GIT_DIR/next-index$$"
-rm -f "$NEXT_INDEX"
-save_index () {
- cp -p "$THIS_INDEX" "$NEXT_INDEX"
-}
-
-run_status () {
- # If TMP_INDEX is defined, that means we are doing
- # "--only" partial commit, and that index file is used
- # to build the tree for the commit. Otherwise, if
- # NEXT_INDEX exists, that is the index file used to
- # make the commit. Otherwise we are using as-is commit
- # so the regular index file is what we use to compare.
- if test '' != "$TMP_INDEX"
- then
- GIT_INDEX_FILE="$TMP_INDEX"
- export GIT_INDEX_FILE
- elif test -f "$NEXT_INDEX"
- then
- GIT_INDEX_FILE="$NEXT_INDEX"
- export GIT_INDEX_FILE
- fi
-
- if test "$status_only" = "t" || test "$use_status_color" = "t"; then
- color=
- else
- color=--nocolor
- fi
- git runstatus ${color} \
- ${verbose:+--verbose} \
- ${amend:+--amend} \
- ${untracked_files:+--untracked}
-}
-
-trap '
- test -z "$TMP_INDEX" || {
- test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
- }
- rm -f "$NEXT_INDEX"
-' 0
-
-################################################################
-# Command line argument parsing and sanity checking
-
-all=
-also=
-allow_empty=f
-interactive=
-only=
-logfile=
-use_commit=
-amend=
-edit_flag=
-no_edit=
-log_given=
-log_message=
-verify=t
-quiet=
-verbose=
-signoff=
-force_author=
-only_include_assumed=
-untracked_files=
-templatefile="$(git config commit.template)"
-while test $# != 0
-do
- case "$1" in
- -F|--F|-f|--f|--fi|--fil|--file)
- case "$#" in 1) usage ;; esac
- shift
- no_edit=t
- log_given=t$log_given
- logfile="$1"
- ;;
- -F*|-f*)
- no_edit=t
- log_given=t$log_given
- logfile="${1#-[Ff]}"
- ;;
- --F=*|--f=*|--fi=*|--fil=*|--file=*)
- no_edit=t
- log_given=t$log_given
- logfile="${1#*=}"
- ;;
- -a|--a|--al|--all)
- all=t
- ;;
- --allo|--allow|--allow-|--allow-e|--allow-em|--allow-emp|\
- --allow-empt|--allow-empty)
- allow_empty=t
- ;;
- --au=*|--aut=*|--auth=*|--autho=*|--author=*)
- force_author="${1#*=}"
- ;;
- --au|--aut|--auth|--autho|--author)
- case "$#" in 1) usage ;; esac
- shift
- force_author="$1"
- ;;
- -e|--e|--ed|--edi|--edit)
- edit_flag=t
- ;;
- -i|--i|--in|--inc|--incl|--inclu|--includ|--include)
- also=t
- ;;
- --int|--inte|--inter|--intera|--interac|--interact|--interacti|\
- --interactiv|--interactive)
- interactive=t
- ;;
- -o|--o|--on|--onl|--only)
- only=t
- ;;
- -m|--m|--me|--mes|--mess|--messa|--messag|--message)
- case "$#" in 1) usage ;; esac
- shift
- log_given=m$log_given
- log_message="${log_message:+${log_message}
-
-}$1"
- no_edit=t
- ;;
- -m*)
- log_given=m$log_given
- log_message="${log_message:+${log_message}
-
-}${1#-m}"
- no_edit=t
- ;;
- --m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
- log_given=m$log_given
- log_message="${log_message:+${log_message}
-
-}${1#*=}"
- no_edit=t
- ;;
- -n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|\
- --no-verify)
- verify=
- ;;
- --a|--am|--ame|--amen|--amend)
- amend=t
- use_commit=HEAD
- ;;
- -c)
- case "$#" in 1) usage ;; esac
- shift
- log_given=t$log_given
- use_commit="$1"
- no_edit=
- ;;
- --ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\
- --reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\
- --reedit-messag=*|--reedit-message=*)
- log_given=t$log_given
- use_commit="${1#*=}"
- no_edit=
- ;;
- --ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\
- --reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|\
- --reedit-message)
- case "$#" in 1) usage ;; esac
- shift
- log_given=t$log_given
- use_commit="$1"
- no_edit=
- ;;
- -C)
- case "$#" in 1) usage ;; esac
- shift
- log_given=t$log_given
- use_commit="$1"
- no_edit=t
- ;;
- --reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\
- --reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\
- --reuse-message=*)
- log_given=t$log_given
- use_commit="${1#*=}"
- no_edit=t
- ;;
- --reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\
- --reuse-mess|--reuse-messa|--reuse-messag|--reuse-message)
- case "$#" in 1) usage ;; esac
- shift
- log_given=t$log_given
- use_commit="$1"
- no_edit=t
- ;;
- -s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
- signoff=t
- ;;
- -t|--t|--te|--tem|--temp|--templ|--templa|--templat|--template)
- case "$#" in 1) usage ;; esac
- shift
- templatefile="$1"
- no_edit=
- ;;
- -q|--q|--qu|--qui|--quie|--quiet)
- quiet=t
- ;;
- -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
- verbose=t
- ;;
- -u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|\
- --untracked|--untracked-|--untracked-f|--untracked-fi|--untracked-fil|\
- --untracked-file|--untracked-files)
- untracked_files=t
- ;;
- --)
- shift
- break
- ;;
- -*)
- usage
- ;;
- *)
- break
- ;;
- esac
- shift
-done
-case "$edit_flag" in t) no_edit= ;; esac
-
-################################################################
-# Sanity check options
-
-case "$amend,$initial_commit" in
-t,t)
- die "You do not have anything to amend." ;;
-t,)
- if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
- die "You are in the middle of a merge -- cannot amend."
- fi ;;
-esac
-
-case "$log_given" in
-tt*)
- die "Only one of -c/-C/-F can be used." ;;
-*tm*|*mt*)
- die "Option -m cannot be combined with -c/-C/-F." ;;
-esac
-
-case "$#,$also,$only,$amend" in
-*,t,t,*)
- die "Only one of --include/--only can be used." ;;
-0,t,,* | 0,,t,)
- die "No paths with --include/--only does not make sense." ;;
-0,,t,t)
- only_include_assumed="# Clever... amending the last one with dirty index." ;;
-0,,,*)
- ;;
-*,,,*)
- only_include_assumed="# Explicit paths specified without -i or -o; assuming --only paths..."
- also=
- ;;
-esac
-unset only
-case "$all,$interactive,$also,$#" in
-*t,*t,*)
- die "Cannot use -a, --interactive or -i at the same time." ;;
-t,,,[1-9]*)
- die "Paths with -a does not make sense." ;;
-,t,,[1-9]*)
- die "Paths with --interactive does not make sense." ;;
-,,t,0)
- die "No paths with -i does not make sense." ;;
-esac
-
-if test ! -z "$templatefile" && test -z "$log_given"
-then
- if test ! -f "$templatefile"
- then
- die "Commit template file does not exist."
- fi
-fi
-
-################################################################
-# Prepare index to have a tree to be committed
-
-case "$all,$also" in
-t,)
- if test ! -f "$THIS_INDEX"
- then
- die 'nothing to commit (use "git add file1 file2" to include for commit)'
- fi
- save_index &&
- (
- cd_to_toplevel &&
- GIT_INDEX_FILE="$NEXT_INDEX" &&
- export GIT_INDEX_FILE &&
- git diff-files --name-only -z |
- git update-index --remove -z --stdin
- ) || exit
- ;;
-,t)
- save_index &&
- git ls-files --error-unmatch -- "$@" >/dev/null || exit
-
- git diff-files --name-only -z -- "$@" |
- (
- cd_to_toplevel &&
- GIT_INDEX_FILE="$NEXT_INDEX" &&
- export GIT_INDEX_FILE &&
- git update-index --remove -z --stdin
- ) || exit
- ;;
-,)
- if test "$interactive" = t; then
- git add --interactive || exit
- fi
- case "$#" in
- 0)
- ;; # commit as-is
- *)
- if test -f "$GIT_DIR/MERGE_HEAD"
- then
- refuse_partial "Cannot do a partial commit during a merge."
- fi
-
- TMP_INDEX="$GIT_DIR/tmp-index$$"
- W=
- test -z "$initial_commit" && W=--with-tree=HEAD
- commit_only=$(git ls-files --error-unmatch $W -- "$@") || exit
-
- # Build a temporary index and update the real index
- # the same way.
- if test -z "$initial_commit"
- then
- GIT_INDEX_FILE="$THIS_INDEX" \
- git read-tree --index-output="$TMP_INDEX" -i -m HEAD
- else
- rm -f "$TMP_INDEX"
- fi || exit
-
- printf '%s\n' "$commit_only" |
- GIT_INDEX_FILE="$TMP_INDEX" \
- git update-index --add --remove --stdin &&
-
- save_index &&
- printf '%s\n' "$commit_only" |
- (
- GIT_INDEX_FILE="$NEXT_INDEX"
- export GIT_INDEX_FILE
- git update-index --add --remove --stdin
- ) || exit
- ;;
- esac
- ;;
-esac
-
-################################################################
-# If we do as-is commit, the index file will be THIS_INDEX,
-# otherwise NEXT_INDEX after we make this commit. We leave
-# the index as is if we abort.
-
-if test -f "$NEXT_INDEX"
-then
- USE_INDEX="$NEXT_INDEX"
-else
- USE_INDEX="$THIS_INDEX"
-fi
-
-case "$status_only" in
-t)
- # This will silently fail in a read-only repository, which is
- # what we want.
- GIT_INDEX_FILE="$USE_INDEX" git update-index -q --unmerged --refresh
- run_status
- exit $?
- ;;
-'')
- GIT_INDEX_FILE="$USE_INDEX" git update-index -q --refresh || exit
- ;;
-esac
-
-################################################################
-# Grab commit message, write out tree and make commit.
-
-if test t = "$verify" && test -x "$GIT_DIR"/hooks/pre-commit
-then
- GIT_INDEX_FILE="${TMP_INDEX:-${USE_INDEX}}" "$GIT_DIR"/hooks/pre-commit \
- || exit
-fi
-
-if test "$log_message" != ''
-then
- printf '%s\n' "$log_message"
-elif test "$logfile" != ""
-then
- if test "$logfile" = -
- then
- test -t 0 &&
- echo >&2 "(reading log message from standard input)"
- cat
- else
- cat <"$logfile"
- fi
-elif test "$use_commit" != ""
-then
- encoding=$(git config i18n.commitencoding || echo UTF-8)
- git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
- sed -e '1,/^$/d' -e 's/^ //'
-elif test -f "$GIT_DIR/MERGE_MSG"
-then
- cat "$GIT_DIR/MERGE_MSG"
-elif test -f "$GIT_DIR/SQUASH_MSG"
-then
- cat "$GIT_DIR/SQUASH_MSG"
-elif test "$templatefile" != ""
-then
- cat "$templatefile"
-fi | git stripspace >"$GIT_DIR"/COMMIT_EDITMSG
-
-case "$signoff" in
-t)
- sign=$(git var GIT_COMMITTER_IDENT | sed -e '
- s/>.*/>/
- s/^/Signed-off-by: /
- ')
- blank_before_signoff=
- tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
- grep 'Signed-off-by:' >/dev/null || blank_before_signoff='
-'
- tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
- grep "$sign"$ >/dev/null ||
- printf '%s%s\n' "$blank_before_signoff" "$sign" \
- >>"$GIT_DIR"/COMMIT_EDITMSG
- ;;
-esac
-
-if test -f "$GIT_DIR/MERGE_HEAD" && test -z "$no_edit"; then
- echo "#"
- echo "# It looks like you may be committing a MERGE."
- echo "# If this is not correct, please remove the file"
- printf '%s\n' "# $GIT_DIR/MERGE_HEAD"
- echo "# and try again"
- echo "#"
-fi >>"$GIT_DIR"/COMMIT_EDITMSG
-
-# Author
-if test '' != "$use_commit"
-then
- eval "$(get_author_ident_from_commit "$use_commit")"
- export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
-fi
-if test '' != "$force_author"
-then
- GIT_AUTHOR_NAME=$(expr "z$force_author" : 'z\(.*[^ ]\) *<.*') &&
- GIT_AUTHOR_EMAIL=$(expr "z$force_author" : '.*\(<.*\)') &&
- test '' != "$GIT_AUTHOR_NAME" &&
- test '' != "$GIT_AUTHOR_EMAIL" ||
- die "malformed --author parameter"
- export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
-fi
-
-PARENTS="-p HEAD"
-if test -z "$initial_commit"
-then
- rloga='commit'
- if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
- rloga='commit (merge)'
- PARENTS="-p HEAD "$(sed -e 's/^/-p /' "$GIT_DIR/MERGE_HEAD")
- elif test -n "$amend"; then
- rloga='commit (amend)'
- PARENTS=$(git cat-file commit HEAD |
- sed -n -e '/^$/q' -e 's/^parent /-p /p')
- fi
- current="$(git rev-parse --verify HEAD)"
-else
- if [ -z "$(git ls-files)" ]; then
- echo >&2 'nothing to commit (use "git add file1 file2" to include for commit)'
- exit 1
- fi
- PARENTS=""
- rloga='commit (initial)'
- current=''
-fi
-set_reflog_action "$rloga"
-
-if test -z "$no_edit"
-then
- {
- echo ""
- echo "# Please enter the commit message for your changes."
- echo "# (Comment lines starting with '#' will not be included)"
- test -z "$only_include_assumed" || echo "$only_include_assumed"
- run_status
- } >>"$GIT_DIR"/COMMIT_EDITMSG
-else
- # we need to check if there is anything to commit
- run_status >/dev/null
-fi
-case "$allow_empty,$?,$PARENTS" in
-t,* | ?,0,* | ?,*,-p' '?*-p' '?*)
- # an explicit --allow-empty, or a merge commit can record the
- # same tree as its parent. Otherwise having commitable paths
- # is required.
- ;;
-*)
- rm -f "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
- use_status_color=t
- run_status
- exit 1
-esac
-
-case "$no_edit" in
-'')
- git var GIT_AUTHOR_IDENT > /dev/null || die
- git var GIT_COMMITTER_IDENT > /dev/null || die
- git_editor "$GIT_DIR/COMMIT_EDITMSG"
- ;;
-esac
-
-case "$verify" in
-t)
- if test -x "$GIT_DIR"/hooks/commit-msg
- then
- "$GIT_DIR"/hooks/commit-msg "$GIT_DIR"/COMMIT_EDITMSG || exit
- fi
-esac
-
-if test -z "$no_edit"
-then
- sed -e '
- /^diff --git a\/.*/{
- s///
- q
- }
- /^#/d
- ' "$GIT_DIR"/COMMIT_EDITMSG
-else
- cat "$GIT_DIR"/COMMIT_EDITMSG
-fi |
-git stripspace >"$GIT_DIR"/COMMIT_MSG
-
-# Test whether the commit message has any content we didn't supply.
-have_commitmsg=
-grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
- git stripspace > "$GIT_DIR"/COMMIT_BAREMSG
-
-# Is the commit message totally empty?
-if test -s "$GIT_DIR"/COMMIT_BAREMSG
-then
- if test "$templatefile" != ""
- then
- # Test whether this is just the unaltered template.
- if cnt=$(sed -e '/^#/d' < "$templatefile" |
- git stripspace |
- diff "$GIT_DIR"/COMMIT_BAREMSG - |
- wc -l) &&
- test 0 -lt $cnt
- then
- have_commitmsg=t
- fi
- else
- # No template, so the content in the commit message must
- # have come from the user.
- have_commitmsg=t
- fi
-fi
-
-rm -f "$GIT_DIR"/COMMIT_BAREMSG
-
-if test "$have_commitmsg" = "t"
-then
- if test -z "$TMP_INDEX"
- then
- tree=$(GIT_INDEX_FILE="$USE_INDEX" git write-tree)
- else
- tree=$(GIT_INDEX_FILE="$TMP_INDEX" git write-tree) &&
- rm -f "$TMP_INDEX"
- fi &&
- commit=$(git commit-tree $tree $PARENTS <"$GIT_DIR/COMMIT_MSG") &&
- rlogm=$(sed -e 1q "$GIT_DIR"/COMMIT_MSG) &&
- git update-ref -m "$GIT_REFLOG_ACTION: $rlogm" HEAD $commit "$current" &&
- rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" &&
- if test -f "$NEXT_INDEX"
- then
- mv "$NEXT_INDEX" "$THIS_INDEX"
- else
- : ;# happy
- fi
-else
- echo >&2 "* no commit message? aborting commit."
- false
-fi
-ret="$?"
-rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
-
-cd_to_toplevel
-
-git rerere
-
-if test "$ret" = 0
-then
- git gc --auto
- if test -x "$GIT_DIR"/hooks/post-commit
- then
- "$GIT_DIR"/hooks/post-commit
- fi
- if test -z "$quiet"
- then
- commit=$(git diff-tree --always --shortstat --pretty="format:%h: %s"\
- --abbrev --summary --root HEAD --)
- echo "Created${initial_commit:+ initial} commit $commit"
- fi
-fi
-
-exit "$ret"
+++ /dev/null
-#!/usr/bin/perl
-# Copyright (c) 2009, 2010 David Aguilar
-# Copyright (c) 2012 Tim Henigan
-#
-# This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
-# git-difftool--helper script.
-#
-# This script exports GIT_EXTERNAL_DIFF and GIT_PAGER for use by git.
-# The GIT_DIFF* variables are exported for use by git-difftool--helper.
-#
-# Any arguments that are unknown to this script are forwarded to 'git diff'.
-
-use 5.008;
-use strict;
-use warnings;
-use Git::LoadCPAN::Error qw(:try);
-use File::Basename qw(dirname);
-use File::Copy;
-use File::Find;
-use File::stat;
-use File::Path qw(mkpath rmtree);
-use File::Temp qw(tempdir);
-use Getopt::Long qw(:config pass_through);
-use Git;
-use Git::I18N;
-
-sub usage
-{
- my $exitcode = shift;
- print << 'USAGE';
-usage: git difftool [-t|--tool=<tool>] [--tool-help]
- [-x|--extcmd=<cmd>]
- [-g|--gui] [--no-gui]
- [--prompt] [-y|--no-prompt]
- [-d|--dir-diff]
- ['git diff' options]
-USAGE
- exit($exitcode);
-}
-
-sub print_tool_help
-{
- # See the comment at the bottom of file_diff() for the reason behind
- # using system() followed by exit() instead of exec().
- my $rc = system(qw(git mergetool --tool-help=diff));
- exit($rc | ($rc >> 8));
-}
-
-sub exit_cleanup
-{
- my ($tmpdir, $status) = @_;
- my $errno = $!;
- rmtree($tmpdir);
- if ($status and $errno) {
- my ($package, $file, $line) = caller();
- warn "$file line $line: $errno\n";
- }
- exit($status | ($status >> 8));
-}
-
-sub use_wt_file
-{
- my ($file, $sha1) = @_;
- my $null_sha1 = '0' x 40;
-
- if (-l $file || ! -e _) {
- return (0, $null_sha1);
- }
-
- my $wt_sha1 = Git::command_oneline('hash-object', $file);
- my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1);
- return ($use, $wt_sha1);
-}
-
-sub changed_files
-{
- my ($repo_path, $index, $worktree) = @_;
- $ENV{GIT_INDEX_FILE} = $index;
-
- my @gitargs = ('--git-dir', $repo_path, '--work-tree', $worktree);
- my @refreshargs = (
- @gitargs, 'update-index',
- '--really-refresh', '-q', '--unmerged');
- try {
- Git::command_oneline(@refreshargs);
- } catch Git::Error::Command with {};
-
- my @diffargs = (@gitargs, 'diff-files', '--name-only', '-z');
- my $line = Git::command_oneline(@diffargs);
- my @files;
- if (defined $line) {
- @files = split('\0', $line);
- } else {
- @files = ();
- }
-
- delete($ENV{GIT_INDEX_FILE});
-
- return map { $_ => 1 } @files;
-}
-
-sub setup_dir_diff
-{
- my ($worktree, $symlinks) = @_;
- my @gitargs = ('diff', '--raw', '--no-abbrev', '-z', @ARGV);
- my $diffrtn = Git::command_oneline(@gitargs);
- exit(0) unless defined($diffrtn);
-
- # Go to the root of the worktree now that we've captured the list of
- # changed files. The paths returned by diff --raw are relative to the
- # top-level of the repository, but we defer changing directories so
- # that @ARGV can perform pathspec limiting in the current directory.
- chdir($worktree);
-
- # Build index info for left and right sides of the diff
- my $submodule_mode = '160000';
- my $symlink_mode = '120000';
- my $null_mode = '0' x 6;
- my $null_sha1 = '0' x 40;
- my $lindex = '';
- my $rindex = '';
- my $wtindex = '';
- my %submodule;
- my %symlink;
- my @files = ();
- my %working_tree_dups = ();
- my @rawdiff = split('\0', $diffrtn);
-
- my $i = 0;
- while ($i < $#rawdiff) {
- if ($rawdiff[$i] =~ /^::/) {
- warn __ <<'EOF';
-Combined diff formats ('-c' and '--cc') are not supported in
-directory diff mode ('-d' and '--dir-diff').
-EOF
- exit(1);
- }
-
- my ($lmode, $rmode, $lsha1, $rsha1, $status) =
- split(' ', substr($rawdiff[$i], 1));
- my $src_path = $rawdiff[$i + 1];
- my $dst_path;
-
- if ($status =~ /^[CR]/) {
- $dst_path = $rawdiff[$i + 2];
- $i += 3;
- } else {
- $dst_path = $src_path;
- $i += 2;
- }
-
- if ($lmode eq $submodule_mode or $rmode eq $submodule_mode) {
- $submodule{$src_path}{left} = $lsha1;
- if ($lsha1 ne $rsha1) {
- $submodule{$dst_path}{right} = $rsha1;
- } else {
- $submodule{$dst_path}{right} = "$rsha1-dirty";
- }
- next;
- }
-
- if ($lmode eq $symlink_mode) {
- $symlink{$src_path}{left} =
- Git::command_oneline('show', $lsha1);
- }
-
- if ($rmode eq $symlink_mode) {
- $symlink{$dst_path}{right} =
- Git::command_oneline('show', $rsha1);
- }
-
- if ($lmode ne $null_mode and $status !~ /^C/) {
- $lindex .= "$lmode $lsha1\t$src_path\0";
- }
-
- if ($rmode ne $null_mode) {
- # Avoid duplicate entries
- if ($working_tree_dups{$dst_path}++) {
- next;
- }
- my ($use, $wt_sha1) =
- use_wt_file($dst_path, $rsha1);
- if ($use) {
- push @files, $dst_path;
- $wtindex .= "$rmode $wt_sha1\t$dst_path\0";
- } else {
- $rindex .= "$rmode $rsha1\t$dst_path\0";
- }
- }
- }
-
- # Go to the root of the worktree so that the left index files
- # are properly setup -- the index is toplevel-relative.
- chdir($worktree);
-
- # Setup temp directories
- my $tmpdir = tempdir('git-difftool.XXXXX', CLEANUP => 0, TMPDIR => 1);
- my $ldir = "$tmpdir/left";
- my $rdir = "$tmpdir/right";
- mkpath($ldir) or exit_cleanup($tmpdir, 1);
- mkpath($rdir) or exit_cleanup($tmpdir, 1);
-
- # Populate the left and right directories based on each index file
- my ($inpipe, $ctx);
- $ENV{GIT_INDEX_FILE} = "$tmpdir/lindex";
- ($inpipe, $ctx) =
- Git::command_input_pipe('update-index', '-z', '--index-info');
- print($inpipe $lindex);
- Git::command_close_pipe($inpipe, $ctx);
-
- my $rc = system('git', 'checkout-index', '--all', "--prefix=$ldir/");
- exit_cleanup($tmpdir, $rc) if $rc != 0;
-
- $ENV{GIT_INDEX_FILE} = "$tmpdir/rindex";
- ($inpipe, $ctx) =
- Git::command_input_pipe('update-index', '-z', '--index-info');
- print($inpipe $rindex);
- Git::command_close_pipe($inpipe, $ctx);
-
- $rc = system('git', 'checkout-index', '--all', "--prefix=$rdir/");
- exit_cleanup($tmpdir, $rc) if $rc != 0;
-
- $ENV{GIT_INDEX_FILE} = "$tmpdir/wtindex";
- ($inpipe, $ctx) =
- Git::command_input_pipe('update-index', '--info-only', '-z', '--index-info');
- print($inpipe $wtindex);
- Git::command_close_pipe($inpipe, $ctx);
-
- # If $GIT_DIR was explicitly set just for the update/checkout
- # commands, then it should be unset before continuing.
- delete($ENV{GIT_INDEX_FILE});
-
- # Changes in the working tree need special treatment since they are
- # not part of the index.
- for my $file (@files) {
- my $dir = dirname($file);
- unless (-d "$rdir/$dir") {
- mkpath("$rdir/$dir") or
- exit_cleanup($tmpdir, 1);
- }
- if ($symlinks) {
- symlink("$worktree/$file", "$rdir/$file") or
- exit_cleanup($tmpdir, 1);
- } else {
- copy($file, "$rdir/$file") or
- exit_cleanup($tmpdir, 1);
-
- my $mode = stat($file)->mode;
- chmod($mode, "$rdir/$file") or
- exit_cleanup($tmpdir, 1);
- }
- }
-
- # Changes to submodules require special treatment. This loop writes a
- # temporary file to both the left and right directories to show the
- # change in the recorded SHA1 for the submodule.
- for my $path (keys %submodule) {
- my $ok = 0;
- if (defined($submodule{$path}{left})) {
- $ok = write_to_file("$ldir/$path",
- "Subproject commit $submodule{$path}{left}");
- }
- if (defined($submodule{$path}{right})) {
- $ok = write_to_file("$rdir/$path",
- "Subproject commit $submodule{$path}{right}");
- }
- exit_cleanup($tmpdir, 1) if not $ok;
- }
-
- # Symbolic links require special treatment. The standard "git diff"
- # shows only the link itself, not the contents of the link target.
- # This loop replicates that behavior.
- for my $path (keys %symlink) {
- my $ok = 0;
- if (defined($symlink{$path}{left})) {
- $ok = write_to_file("$ldir/$path",
- $symlink{$path}{left});
- }
- if (defined($symlink{$path}{right})) {
- $ok = write_to_file("$rdir/$path",
- $symlink{$path}{right});
- }
- exit_cleanup($tmpdir, 1) if not $ok;
- }
-
- return ($ldir, $rdir, $tmpdir, @files);
-}
-
-sub write_to_file
-{
- my $path = shift;
- my $value = shift;
-
- # Make sure the path to the file exists
- my $dir = dirname($path);
- unless (-d "$dir") {
- mkpath("$dir") or return 0;
- }
-
- # If the file already exists in that location, delete it. This
- # is required in the case of symbolic links.
- unlink($path);
-
- open(my $fh, '>', $path) or return 0;
- print($fh $value);
- close($fh);
-
- return 1;
-}
-
-sub main
-{
- # parse command-line options. all unrecognized options and arguments
- # are passed through to the 'git diff' command.
- my %opts = (
- difftool_cmd => undef,
- dirdiff => undef,
- extcmd => undef,
- gui => undef,
- help => undef,
- prompt => undef,
- symlinks => $^O ne 'cygwin' &&
- $^O ne 'MSWin32' && $^O ne 'msys',
- tool_help => undef,
- trust_exit_code => undef,
- );
- GetOptions('g|gui!' => \$opts{gui},
- 'd|dir-diff' => \$opts{dirdiff},
- 'h' => \$opts{help},
- 'prompt!' => \$opts{prompt},
- 'y' => sub { $opts{prompt} = 0; },
- 'symlinks' => \$opts{symlinks},
- 'no-symlinks' => sub { $opts{symlinks} = 0; },
- 't|tool:s' => \$opts{difftool_cmd},
- 'tool-help' => \$opts{tool_help},
- 'trust-exit-code' => \$opts{trust_exit_code},
- 'no-trust-exit-code' => sub { $opts{trust_exit_code} = 0; },
- 'x|extcmd:s' => \$opts{extcmd});
-
- if (defined($opts{help})) {
- usage(0);
- }
- if (defined($opts{tool_help})) {
- print_tool_help();
- }
- if (defined($opts{difftool_cmd})) {
- if (length($opts{difftool_cmd}) > 0) {
- $ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};
- } else {
- print __("No <tool> given for --tool=<tool>\n");
- usage(1);
- }
- }
- if (defined($opts{extcmd})) {
- if (length($opts{extcmd}) > 0) {
- $ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};
- } else {
- print __("No <cmd> given for --extcmd=<cmd>\n");
- usage(1);
- }
- }
- if ($opts{gui}) {
- my $guitool = Git::config('diff.guitool');
- if (defined($guitool) && length($guitool) > 0) {
- $ENV{GIT_DIFF_TOOL} = $guitool;
- }
- }
-
- if (!defined $opts{trust_exit_code}) {
- $opts{trust_exit_code} = Git::config_bool('difftool.trustExitCode');
- }
- if ($opts{trust_exit_code}) {
- $ENV{GIT_DIFFTOOL_TRUST_EXIT_CODE} = 'true';
- } else {
- $ENV{GIT_DIFFTOOL_TRUST_EXIT_CODE} = 'false';
- }
-
- # In directory diff mode, 'git-difftool--helper' is called once
- # to compare the a/b directories. In file diff mode, 'git diff'
- # will invoke a separate instance of 'git-difftool--helper' for
- # each file that changed.
- if (defined($opts{dirdiff})) {
- dir_diff($opts{extcmd}, $opts{symlinks});
- } else {
- file_diff($opts{prompt});
- }
-}
-
-sub dir_diff
-{
- my ($extcmd, $symlinks) = @_;
- my $rc;
- my $error = 0;
- my $repo = Git->repository();
- my $repo_path = $repo->repo_path();
- my $worktree = $repo->wc_path();
- $worktree =~ s|/$||; # Avoid double slashes in symlink targets
- my ($a, $b, $tmpdir, @files) = setup_dir_diff($worktree, $symlinks);
-
- if (defined($extcmd)) {
- $rc = system($extcmd, $a, $b);
- } else {
- $ENV{GIT_DIFFTOOL_DIRDIFF} = 'true';
- $rc = system('git', 'difftool--helper', $a, $b);
- }
- # If the diff including working copy files and those
- # files were modified during the diff, then the changes
- # should be copied back to the working tree.
- # Do not copy back files when symlinks are used and the
- # external tool did not replace the original link with a file.
- #
- # These hashes are loaded lazily since they aren't needed
- # in the common case of --symlinks and the difftool updating
- # files through the symlink.
- my %wt_modified;
- my %tmp_modified;
- my $indices_loaded = 0;
-
- for my $file (@files) {
- next if $symlinks && -l "$b/$file";
- next if ! -f "$b/$file";
-
- if (!$indices_loaded) {
- %wt_modified = changed_files(
- $repo_path, "$tmpdir/wtindex", $worktree);
- %tmp_modified = changed_files(
- $repo_path, "$tmpdir/wtindex", $b);
- $indices_loaded = 1;
- }
-
- if (exists $wt_modified{$file} and exists $tmp_modified{$file}) {
- warn sprintf(__(
- "warning: Both files modified:\n" .
- "'%s/%s' and '%s/%s'.\n" .
- "warning: Working tree file has been left.\n" .
- "warning:\n"), $worktree, $file, $b, $file);
- $error = 1;
- } elsif (exists $tmp_modified{$file}) {
- my $mode = stat("$b/$file")->mode;
- copy("$b/$file", $file) or
- exit_cleanup($tmpdir, 1);
-
- chmod($mode, $file) or
- exit_cleanup($tmpdir, 1);
- }
- }
- if ($error) {
- warn sprintf(__(
- "warning: Temporary files exist in '%s'.\n" .
- "warning: You may want to cleanup or recover these.\n"), $tmpdir);
- exit(1);
- } else {
- exit_cleanup($tmpdir, $rc);
- }
-}
-
-sub file_diff
-{
- my ($prompt) = @_;
-
- if (defined($prompt)) {
- if ($prompt) {
- $ENV{GIT_DIFFTOOL_PROMPT} = 'true';
- } else {
- $ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
- }
- }
-
- $ENV{GIT_PAGER} = '';
- $ENV{GIT_EXTERNAL_DIFF} = 'git-difftool--helper';
-
- # ActiveState Perl for Win32 does not implement POSIX semantics of
- # exec* system call. It just spawns the given executable and finishes
- # the starting program, exiting with code 0.
- # system will at least catch the errors returned by git diff,
- # allowing the caller of git difftool better handling of failures.
- my $rc = system('git', 'diff', @ARGV);
- exit($rc | ($rc >> 8));
-}
-
-main();
+++ /dev/null
-#!/bin/sh
-#
-
-USAGE='<fetch-options> <repository> <refspec>...'
-SUBDIRECTORY_OK=Yes
-. git-sh-setup
-set_reflog_action "fetch $*"
-cd_to_toplevel ;# probably unnecessary...
-
-. git-parse-remote
-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
-_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
-
-LF='
-'
-IFS="$LF"
-
-no_tags=
-tags=
-append=
-force=
-verbose=
-update_head_ok=
-exec=
-keep=
-shallow_depth=
-no_progress=
-test -t 1 || no_progress=--no-progress
-quiet=
-while test $# != 0
-do
- case "$1" in
- -a|--a|--ap|--app|--appe|--appen|--append)
- append=t
- ;;
- --upl|--uplo|--uploa|--upload|--upload-|--upload-p|\
- --upload-pa|--upload-pac|--upload-pack)
- shift
- exec="--upload-pack=$1"
- ;;
- --upl=*|--uplo=*|--uploa=*|--upload=*|\
- --upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
- exec=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)')
- shift
- ;;
- -f|--f|--fo|--for|--forc|--force)
- force=t
- ;;
- -t|--t|--ta|--tag|--tags)
- tags=t
- ;;
- -n|--n|--no|--no-|--no-t|--no-ta|--no-tag|--no-tags)
- no_tags=t
- ;;
- -u|--u|--up|--upd|--upda|--updat|--update|--update-|--update-h|\
- --update-he|--update-hea|--update-head|--update-head-|\
- --update-head-o|--update-head-ok)
- update_head_ok=t
- ;;
- -q|--q|--qu|--qui|--quie|--quiet)
- quiet=--quiet
- ;;
- -v|--verbose)
- verbose="$verbose"Yes
- ;;
- -k|--k|--ke|--kee|--keep)
- keep='-k -k'
- ;;
- --depth=*)
- shallow_depth="--depth=$(expr "z$1" : 'z-[^=]*=\(.*\)')"
- ;;
- --depth)
- shift
- shallow_depth="--depth=$1"
- ;;
- -*)
- usage
- ;;
- *)
- break
- ;;
- esac
- shift
-done
-
-case "$#" in
-0)
- origin=$(get_default_remote)
- test -n "$(get_remote_url ${origin})" ||
- die "Where do you want to fetch from today?"
- set x $origin ; shift ;;
-esac
-
-if test -z "$exec"
-then
- # No command line override and we have configuration for the remote.
- exec="--upload-pack=$(get_uploadpack $1)"
-fi
-
-remote_nick="$1"
-remote=$(get_remote_url "$@")
-refs=
-rref=
-rsync_slurped_objects=
-
-if test "" = "$append"
-then
- : >"$GIT_DIR/FETCH_HEAD"
-fi
-
-# Global that is reused later
-ls_remote_result=$(git ls-remote $exec "$remote") ||
- die "Cannot get the repository state from $remote"
-
-append_fetch_head () {
- flags=
- test -n "$verbose" && flags="$flags$LF-v"
- test -n "$force$single_force" && flags="$flags$LF-f"
- GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \
- git fetch--tool $flags append-fetch-head "$@"
-}
-
-# updating the current HEAD with git-fetch in a bare
-# repository is always fine.
-if test -z "$update_head_ok" && test $(is_bare_repository) = false
-then
- orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
-fi
-
-# Allow --tags/--notags from remote.$1.tagopt
-case "$tags$no_tags" in
-'')
- case "$(git config --get "remote.$1.tagopt")" in
- --tags)
- tags=t ;;
- --no-tags)
- no_tags=t ;;
- esac
-esac
-
-# If --tags (and later --heads or --all) is specified, then we are
-# not talking about defaults stored in Pull: line of remotes or
-# branches file, and just fetch those and refspecs explicitly given.
-# Otherwise we do what we always did.
-
-reflist=$(get_remote_refs_for_fetch "$@")
-if test "$tags"
-then
- taglist=$(IFS=' ' &&
- echo "$ls_remote_result" |
- git show-ref --exclude-existing=refs/tags/ |
- while read sha1 name
- do
- echo ".${name}:${name}"
- done) || exit
- if test "$#" -gt 1
- then
- # remote URL plus explicit refspecs; we need to merge them.
- reflist="$reflist$LF$taglist"
- else
- # No explicit refspecs; fetch tags only.
- reflist=$taglist
- fi
-fi
-
-fetch_all_at_once () {
-
- eval=$(echo "$1" | git fetch--tool parse-reflist "-")
- eval "$eval"
-
- ( : subshell because we muck with IFS
- IFS=" $LF"
- (
- if test "$remote" = . ; then
- git show-ref $rref || echo failed "$remote"
- elif test -f "$remote" ; then
- test -n "$shallow_depth" &&
- die "shallow clone with bundle is not supported"
- git bundle unbundle "$remote" $rref ||
- echo failed "$remote"
- else
- if test -d "$remote" &&
-
- # The remote might be our alternate. With
- # this optimization we will bypass fetch-pack
- # altogether, which means we cannot be doing
- # the shallow stuff at all.
- test ! -f "$GIT_DIR/shallow" &&
- test -z "$shallow_depth" &&
-
- # See if all of what we are going to fetch are
- # connected to our repository's tips, in which
- # case we do not have to do any fetch.
- theirs=$(echo "$ls_remote_result" | \
- git fetch--tool -s pick-rref "$rref" "-") &&
-
- # This will barf when $theirs reach an object that
- # we do not have in our repository. Otherwise,
- # we already have everything the fetch would bring in.
- git rev-list --objects $theirs --not --all \
- >/dev/null 2>/dev/null
- then
- echo "$ls_remote_result" | \
- git fetch--tool pick-rref "$rref" "-"
- else
- flags=
- case $verbose in
- YesYes*)
- flags="-v"
- ;;
- esac
- git-fetch-pack --thin $exec $keep $shallow_depth \
- $quiet $no_progress $flags "$remote" $rref ||
- echo failed "$remote"
- fi
- fi
- ) |
- (
- flags=
- test -n "$verbose" && flags="$flags -v"
- test -n "$force" && flags="$flags -f"
- GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \
- git fetch--tool $flags native-store \
- "$remote" "$remote_nick" "$refs"
- )
- ) || exit
-
-}
-
-fetch_per_ref () {
- reflist="$1"
- refs=
- rref=
-
- for ref in $reflist
- do
- refs="$refs$LF$ref"
-
- # These are relative path from $GIT_DIR, typically starting at refs/
- # but may be HEAD
- if expr "z$ref" : 'z\.' >/dev/null
- then
- not_for_merge=t
- ref=$(expr "z$ref" : 'z\.\(.*\)')
- else
- not_for_merge=
- fi
- if expr "z$ref" : 'z+' >/dev/null
- then
- single_force=t
- ref=$(expr "z$ref" : 'z+\(.*\)')
- else
- single_force=
- fi
- remote_name=$(expr "z$ref" : 'z\([^:]*\):')
- local_name=$(expr "z$ref" : 'z[^:]*:\(.*\)')
-
- rref="$rref$LF$remote_name"
-
- # There are transports that can fetch only one head at a time...
- case "$remote" in
- http://* | https://* | ftp://*)
- test -n "$shallow_depth" &&
- die "shallow clone with http not supported"
- proto=$(expr "$remote" : '\([^:]*\):')
- if [ -n "$GIT_SSL_NO_VERIFY" ]; then
- curl_extra_args="-k"
- fi
- if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
- "$(git config --bool http.noEPSV)" = true ]; then
- noepsv_opt="--disable-epsv"
- fi
-
- # Find $remote_name from ls-remote output.
- head=$(echo "$ls_remote_result" | \
- git fetch--tool -s pick-rref "$remote_name" "-")
- expr "z$head" : "z$_x40\$" >/dev/null ||
- die "No such ref $remote_name at $remote"
- echo >&2 "Fetching $remote_name from $remote using $proto"
- case "$quiet" in '') v=-v ;; *) v= ;; esac
- git-http-fetch $v -a "$head" "$remote" || exit
- ;;
- rsync://*)
- test -n "$shallow_depth" &&
- die "shallow clone with rsync not supported"
- TMP_HEAD="$GIT_DIR/TMP_HEAD"
- rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
- head=$(git rev-parse --verify TMP_HEAD)
- rm -f "$TMP_HEAD"
- case "$quiet" in '') v=-v ;; *) v= ;; esac
- test "$rsync_slurped_objects" || {
- rsync -a $v --ignore-existing --exclude info \
- "$remote/objects/" "$GIT_OBJECT_DIRECTORY/" || exit
-
- # Look at objects/info/alternates for rsync -- http will
- # support it natively and git native ones will do it on
- # the remote end. Not having that file is not a crime.
- rsync -q "$remote/objects/info/alternates" \
- "$GIT_DIR/TMP_ALT" 2>/dev/null ||
- rm -f "$GIT_DIR/TMP_ALT"
- if test -f "$GIT_DIR/TMP_ALT"
- then
- resolve_alternates "$remote" <"$GIT_DIR/TMP_ALT" |
- while read alt
- do
- case "$alt" in 'bad alternate: '*) die "$alt";; esac
- echo >&2 "Getting alternate: $alt"
- rsync -av --ignore-existing --exclude info \
- "$alt" "$GIT_OBJECT_DIRECTORY/" || exit
- done
- rm -f "$GIT_DIR/TMP_ALT"
- fi
- rsync_slurped_objects=t
- }
- ;;
- esac
-
- append_fetch_head "$head" "$remote" \
- "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" || exit
-
- done
-
-}
-
-fetch_main () {
- case "$remote" in
- http://* | https://* | ftp://* | rsync://* )
- fetch_per_ref "$@"
- ;;
- *)
- fetch_all_at_once "$@"
- ;;
- esac
-}
-
-fetch_main "$reflist" || exit
-
-# automated tag following
-case "$no_tags$tags" in
-'')
- case "$reflist" in
- *:refs/*)
- # effective only when we are following remote branch
- # using local tracking branch.
- taglist=$(IFS=' ' &&
- echo "$ls_remote_result" |
- git show-ref --exclude-existing=refs/tags/ |
- while read sha1 name
- do
- git cat-file -t "$sha1" >/dev/null 2>&1 || continue
- echo >&2 "Auto-following $name"
- echo ".${name}:${name}"
- done)
- esac
- case "$taglist" in
- '') ;;
- ?*)
- # do not deepen a shallow tree when following tags
- shallow_depth=
- fetch_main "$taglist" || exit ;;
- esac
-esac
-
-# If the original head was empty (i.e. no "master" yet), or
-# if we were told not to worry, we do not have to check.
-case "$orig_head" in
-'')
- ;;
-?*)
- curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
- if test "$curr_head" != "$orig_head"
- then
- git update-ref \
- -m "$GIT_REFLOG_ACTION: Undoing incorrectly fetched HEAD." \
- HEAD "$orig_head"
- die "Cannot fetch into the current branch."
- fi
- ;;
-esac
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2006, Shawn O. Pearce
-#
-# Cleanup unreachable files and optimize the repository.
-
-USAGE='[--prune]'
-SUBDIRECTORY_OK=Yes
-. git-sh-setup
-
-no_prune=:
-while test $# != 0
-do
- case "$1" in
- --prune)
- no_prune=
- ;;
- --)
- usage
- ;;
- esac
- shift
-done
-
-case "$(git config --get gc.packrefs)" in
-notbare|"")
- test $(is_bare_repository) = true || pack_refs=true;;
-*)
- pack_refs=$(git config --bool --get gc.packrefs)
-esac
-
-test "true" != "$pack_refs" ||
-git pack-refs --prune &&
-git reflog expire --all &&
-git-repack -a -d -l &&
-$no_prune git prune &&
-git rerere gc || exit
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-
-USAGE='[--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [git-rev-list options]'
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
-[ "$revs" ] || {
- die "No HEAD ref"
-}
-git-rev-list --pretty $(git-rev-parse --default HEAD "$@") |
-LESS=-S ${PAGER:-less}
+++ /dev/null
-#!/bin/sh
-#
-
-usage () {
- echo >&2 "usage: $0 [--heads] [--tags] [-u|--upload-pack <upload-pack>]"
- echo >&2 " <repository> <refs>..."
- exit 1;
-}
-
-die () {
- echo >&2 "$*"
- exit 1
-}
-
-exec=
-while test $# != 0
-do
- case "$1" in
- -h|--h|--he|--hea|--head|--heads)
- heads=heads; shift ;;
- -t|--t|--ta|--tag|--tags)
- tags=tags; shift ;;
- -u|--u|--up|--upl|--uploa|--upload|--upload-|--upload-p|--upload-pa|\
- --upload-pac|--upload-pack)
- shift
- exec="--upload-pack=$1"
- shift;;
- -u=*|--u=*|--up=*|--upl=*|--uplo=*|--uploa=*|--upload=*|\
- --upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
- exec=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)')
- shift;;
- --)
- shift; break ;;
- -*)
- usage ;;
- *)
- break ;;
- esac
-done
-
-case "$#" in 0) usage ;; esac
-
-case ",$heads,$tags," in
-,,,) heads=heads tags=tags other=other ;;
-esac
-
-. git-parse-remote
-peek_repo="$(get_remote_url "$@")"
-shift
-
-tmp=.ls-remote-$$
-trap "rm -fr $tmp-*" 0 1 2 3 15
-tmpdir=$tmp-d
-
-case "$peek_repo" in
-http://* | https://* | ftp://* )
- if [ -n "$GIT_SSL_NO_VERIFY" -o \
- "$(git config --bool http.sslVerify)" = false ]; then
- curl_extra_args="-k"
- fi
- if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
- "$(git config --bool http.noEPSV)" = true ]; then
- curl_extra_args="${curl_extra_args} --disable-epsv"
- fi
- curl -nsf $curl_extra_args --header "Pragma: no-cache" "$peek_repo/info/refs" ||
- echo "failed slurping"
- ;;
-
-rsync://* )
- mkdir $tmpdir &&
- rsync -rlq "$peek_repo/HEAD" $tmpdir &&
- rsync -rq "$peek_repo/refs" $tmpdir || {
- echo "failed slurping"
- exit
- }
- head=$(cat "$tmpdir/HEAD") &&
- case "$head" in
- ref:' '*)
- head=$(expr "z$head" : 'zref: \(.*\)') &&
- head=$(cat "$tmpdir/$head") || exit
- esac &&
- echo "$head HEAD"
- (cd $tmpdir && find refs -type f) |
- while read path
- do
- tr -d '\012' <"$tmpdir/$path"
- echo " $path"
- done &&
- rm -fr $tmpdir
- ;;
-
-* )
- if test -f "$peek_repo" ; then
- git bundle list-heads "$peek_repo" ||
- echo "failed slurping"
- else
- git-peek-remote $exec "$peek_repo" ||
- echo "failed slurping"
- fi
- ;;
-esac |
-sort -t ' ' -k 2 |
-while read sha1 path
-do
- case "$sha1" in
- failed)
- exit 1 ;;
- esac
- case "$path" in
- refs/heads/*)
- group=heads ;;
- refs/tags/*)
- group=tags ;;
- *)
- group=other ;;
- esac
- case ",$heads,$tags,$other," in
- *,$group,*)
- ;;
- *)
- continue;;
- esac
- case "$#" in
- 0)
- match=yes ;;
- *)
- match=no
- for pat
- do
- case "/$path" in
- */$pat )
- match=yes
- break ;;
- esac
- done
- esac
- case "$match" in
- no)
- continue ;;
- esac
- echo "$sha1 $path"
-done
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Junio C Hamano
-#
-# Pretend we resolved the heads, but declare our tree trumps everybody else.
-#
-
-# We need to exit with 2 if the index does not match our HEAD tree,
-# because the current index is what we will be committing as the
-# merge result.
-
-git diff-index --quiet --cached HEAD -- || exit 2
-
-exit 0
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Junio C Hamano
-#
-
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC="\
-git merge [options] <remote>...
-git merge [options] <msg> HEAD <remote>
---
-stat show a diffstat at the end of the merge
-n don't show a diffstat at the end of the merge
-summary (synonym to --stat)
-log add list of one-line log to merge commit message
-squash create a single commit instead of doing a merge
-commit perform a commit if the merge succeeds (default)
-ff allow fast-forward (default)
-ff-only abort if fast-forward is not possible
-rerere-autoupdate update index with any reused conflict resolution
-s,strategy= merge strategy to use
-X= option for selected merge strategy
-m,message= message to be used for the merge commit (if any)
-"
-
-SUBDIRECTORY_OK=Yes
-. git-sh-setup
-require_work_tree
-cd_to_toplevel
-
-test -z "$(git ls-files -u)" ||
- die "Merge is not possible because you have unmerged files."
-
-! test -e "$GIT_DIR/MERGE_HEAD" ||
- die 'You have not concluded your merge (MERGE_HEAD exists).'
-
-LF='
-'
-
-all_strategies='recur recursive octopus resolve stupid ours subtree'
-all_strategies="$all_strategies recursive-ours recursive-theirs"
-not_strategies='base file index tree'
-default_twohead_strategies='recursive'
-default_octopus_strategies='octopus'
-no_fast_forward_strategies='subtree ours'
-no_trivial_strategies='recursive recur subtree ours recursive-ours recursive-theirs'
-use_strategies=
-xopt=
-
-allow_fast_forward=t
-fast_forward_only=
-allow_trivial_merge=t
-squash= no_commit= log_arg= rr_arg=
-
-dropsave() {
- rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \
- "$GIT_DIR/MERGE_STASH" "$GIT_DIR/MERGE_MODE" || exit 1
-}
-
-savestate() {
- # Stash away any local modifications.
- git stash create >"$GIT_DIR/MERGE_STASH"
-}
-
-restorestate() {
- if test -f "$GIT_DIR/MERGE_STASH"
- then
- git reset --hard $head >/dev/null
- git stash apply $(cat "$GIT_DIR/MERGE_STASH")
- git update-index --refresh >/dev/null
- fi
-}
-
-finish_up_to_date () {
- case "$squash" in
- t)
- echo "$1 (nothing to squash)" ;;
- '')
- echo "$1" ;;
- esac
- dropsave
-}
-
-squash_message () {
- echo Squashed commit of the following:
- echo
- git log --no-merges --pretty=medium ^"$head" $remoteheads
-}
-
-finish () {
- if test '' = "$2"
- then
- rlogm="$GIT_REFLOG_ACTION"
- else
- echo "$2"
- rlogm="$GIT_REFLOG_ACTION: $2"
- fi
- case "$squash" in
- t)
- echo "Squash commit -- not updating HEAD"
- squash_message >"$GIT_DIR/SQUASH_MSG"
- ;;
- '')
- case "$merge_msg" in
- '')
- echo "No merge message -- not updating HEAD"
- ;;
- *)
- git update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
- git gc --auto
- ;;
- esac
- ;;
- esac
- case "$1" in
- '')
- ;;
- ?*)
- if test "$show_diffstat" = t
- then
- # We want color (if set), but no pager
- GIT_PAGER='' git diff --stat --summary -M "$head" "$1"
- fi
- ;;
- esac
-
- # Run a post-merge hook
- if test -x "$GIT_DIR"/hooks/post-merge
- then
- case "$squash" in
- t)
- "$GIT_DIR"/hooks/post-merge 1
- ;;
- '')
- "$GIT_DIR"/hooks/post-merge 0
- ;;
- esac
- fi
-}
-
-merge_name () {
- remote="$1"
- rh=$(git rev-parse --verify "$remote^0" 2>/dev/null) || return
- if truname=$(expr "$remote" : '\(.*\)~[0-9]*$') &&
- git show-ref -q --verify "refs/heads/$truname" 2>/dev/null
- then
- echo "$rh branch '$truname' (early part) of ."
- return
- fi
- if found_ref=$(git rev-parse --symbolic-full-name --verify \
- "$remote" 2>/dev/null)
- then
- expanded=$(git check-ref-format --branch "$remote") ||
- exit
- if test "${found_ref#refs/heads/}" != "$found_ref"
- then
- echo "$rh branch '$expanded' of ."
- return
- elif test "${found_ref#refs/remotes/}" != "$found_ref"
- then
- echo "$rh remote branch '$expanded' of ."
- return
- fi
- fi
- if test "$remote" = "FETCH_HEAD" && test -r "$GIT_DIR/FETCH_HEAD"
- then
- sed -e 's/ not-for-merge / /' -e 1q \
- "$GIT_DIR/FETCH_HEAD"
- return
- fi
- echo "$rh commit '$remote'"
-}
-
-parse_config () {
- while test $# != 0; do
- case "$1" in
- -n|--no-stat|--no-summary)
- show_diffstat=false ;;
- --stat|--summary)
- show_diffstat=t ;;
- --log|--no-log)
- log_arg=$1 ;;
- --squash)
- test "$allow_fast_forward" = t ||
- die "You cannot combine --squash with --no-ff."
- squash=t no_commit=t ;;
- --no-squash)
- squash= no_commit= ;;
- --commit)
- no_commit= ;;
- --no-commit)
- no_commit=t ;;
- --ff)
- allow_fast_forward=t ;;
- --no-ff)
- test "$squash" != t ||
- die "You cannot combine --squash with --no-ff."
- test "$fast_forward_only" != t ||
- die "You cannot combine --ff-only with --no-ff."
- allow_fast_forward=f ;;
- --ff-only)
- test "$allow_fast_forward" != f ||
- die "You cannot combine --ff-only with --no-ff."
- fast_forward_only=t ;;
- --rerere-autoupdate|--no-rerere-autoupdate)
- rr_arg=$1 ;;
- -s|--strategy)
- shift
- case " $all_strategies " in
- *" $1 "*)
- use_strategies="$use_strategies$1 "
- ;;
- *)
- case " $not_strategies " in
- *" $1 "*)
- false
- esac &&
- type "git-merge-$1" >/dev/null 2>&1 ||
- die "available strategies are: $all_strategies"
- use_strategies="$use_strategies$1 "
- ;;
- esac
- ;;
- -X)
- shift
- xopt="${xopt:+$xopt }$(git rev-parse --sq-quote "--$1")"
- ;;
- -m|--message)
- shift
- merge_msg="$1"
- have_message=t
- ;;
- --)
- shift
- break ;;
- *) usage ;;
- esac
- shift
- done
- args_left=$#
-}
-
-test $# != 0 || usage
-
-have_message=
-
-if branch=$(git-symbolic-ref -q HEAD)
-then
- mergeopts=$(git config "branch.${branch#refs/heads/}.mergeoptions")
- if test -n "$mergeopts"
- then
- parse_config $mergeopts --
- fi
-fi
-
-parse_config "$@"
-while test $args_left -lt $#; do shift; done
-
-if test -z "$show_diffstat"; then
- test "$(git config --bool merge.diffstat)" = false && show_diffstat=false
- test "$(git config --bool merge.stat)" = false && show_diffstat=false
- test -z "$show_diffstat" && show_diffstat=t
-fi
-
-# This could be traditional "merge <msg> HEAD <commit>..." and the
-# way we can tell it is to see if the second token is HEAD, but some
-# people might have misused the interface and used a commit-ish that
-# is the same as HEAD there instead. Traditional format never would
-# have "-m" so it is an additional safety measure to check for it.
-
-if test -z "$have_message" &&
- second_token=$(git rev-parse --verify "$2^0" 2>/dev/null) &&
- head_commit=$(git rev-parse --verify "HEAD" 2>/dev/null) &&
- test "$second_token" = "$head_commit"
-then
- merge_msg="$1"
- shift
- head_arg="$1"
- shift
-elif ! git rev-parse --verify HEAD >/dev/null 2>&1
-then
- # If the merged head is a valid one there is no reason to
- # forbid "git merge" into a branch yet to be born. We do
- # the same for "git pull".
- if test 1 -ne $#
- then
- echo >&2 "Can merge only exactly one commit into empty head"
- exit 1
- fi
-
- test "$squash" != t ||
- die "Squash commit into empty head not supported yet"
- test "$allow_fast_forward" = t ||
- die "Non-fast-forward into an empty head does not make sense"
- rh=$(git rev-parse --verify "$1^0") ||
- die "$1 - not something we can merge"
-
- git update-ref -m "initial pull" HEAD "$rh" "" &&
- git read-tree --reset -u HEAD
- exit
-
-else
- # We are invoked directly as the first-class UI.
- head_arg=HEAD
-
- # All the rest are the commits being merged; prepare
- # the standard merge summary message to be appended to
- # the given message. If remote is invalid we will die
- # later in the common codepath so we discard the error
- # in this loop.
- merge_msg="$(
- for remote
- do
- merge_name "$remote"
- done |
- if test "$have_message" = t
- then
- git fmt-merge-msg -m "$merge_msg" $log_arg
- else
- git fmt-merge-msg $log_arg
- fi
- )"
-fi
-head=$(git rev-parse --verify "$head_arg"^0) || usage
-
-# All the rest are remote heads
-test "$#" = 0 && usage ;# we need at least one remote head.
-set_reflog_action "merge $*"
-
-remoteheads=
-for remote
-do
- remotehead=$(git rev-parse --verify "$remote"^0 2>/dev/null) ||
- die "$remote - not something we can merge"
- remoteheads="${remoteheads}$remotehead "
- eval GITHEAD_$remotehead='"$remote"'
- export GITHEAD_$remotehead
-done
-set x $remoteheads ; shift
-
-case "$use_strategies" in
-'')
- case "$#" in
- 1)
- var="$(git config --get pull.twohead)"
- if test -n "$var"
- then
- use_strategies="$var"
- else
- use_strategies="$default_twohead_strategies"
- fi ;;
- *)
- var="$(git config --get pull.octopus)"
- if test -n "$var"
- then
- use_strategies="$var"
- else
- use_strategies="$default_octopus_strategies"
- fi ;;
- esac
- ;;
-esac
-
-for s in $use_strategies
-do
- for ss in $no_fast_forward_strategies
- do
- case " $s " in
- *" $ss "*)
- allow_fast_forward=f
- break
- ;;
- esac
- done
- for ss in $no_trivial_strategies
- do
- case " $s " in
- *" $ss "*)
- allow_trivial_merge=f
- break
- ;;
- esac
- done
-done
-
-case "$#" in
-1)
- common=$(git merge-base --all $head "$@")
- ;;
-*)
- common=$(git merge-base --all --octopus $head "$@")
- ;;
-esac
-echo "$head" >"$GIT_DIR/ORIG_HEAD"
-
-case "$allow_fast_forward,$#,$common,$no_commit" in
-?,*,'',*)
- # No common ancestors found. We need a real merge.
- ;;
-?,1,"$1",*)
- # If head can reach all the merge then we are up to date.
- # but first the most common case of merging one remote.
- finish_up_to_date "Already up to date."
- exit 0
- ;;
-t,1,"$head",*)
- # Again the most common case of merging one remote.
- echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $1)"
- git update-index --refresh 2>/dev/null
- msg="Fast-forward"
- if test -n "$have_message"
- then
- msg="$msg (no commit created; -m option ignored)"
- fi
- new_head=$(git rev-parse --verify "$1^0") &&
- git read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
- finish "$new_head" "$msg" || exit
- dropsave
- exit 0
- ;;
-?,1,?*"$LF"?*,*)
- # We are not doing octopus and not fast-forward. Need a
- # real merge.
- ;;
-?,1,*,)
- # We are not doing octopus, not fast-forward, and have only
- # one common.
- git update-index --refresh 2>/dev/null
- case "$allow_trivial_merge,$fast_forward_only" in
- t,)
- # See if it is really trivial.
- git var GIT_COMMITTER_IDENT >/dev/null || exit
- echo "Trying really trivial in-index merge..."
- if git read-tree --trivial -m -u -v $common $head "$1" &&
- result_tree=$(git write-tree)
- then
- echo "Wonderful."
- result_commit=$(
- printf '%s\n' "$merge_msg" |
- git commit-tree $result_tree -p HEAD -p "$1"
- ) || exit
- finish "$result_commit" "In-index merge"
- dropsave
- exit 0
- fi
- echo "Nope."
- esac
- ;;
-*)
- # An octopus. If we can reach all the remote we are up to date.
- up_to_date=t
- for remote
- do
- common_one=$(git merge-base --all $head $remote)
- if test "$common_one" != "$remote"
- then
- up_to_date=f
- break
- fi
- done
- if test "$up_to_date" = t
- then
- finish_up_to_date "Already up to date. Yeeah!"
- exit 0
- fi
- ;;
-esac
-
-if test "$fast_forward_only" = t
-then
- die "Not possible to fast-forward, aborting."
-fi
-
-# We are going to make a new commit.
-git var GIT_COMMITTER_IDENT >/dev/null || exit
-
-# At this point, we need a real merge. No matter what strategy
-# we use, it would operate on the index, possibly affecting the
-# working tree, and when resolved cleanly, have the desired tree
-# in the index -- this means that the index must be in sync with
-# the $head commit. The strategies are responsible to ensure this.
-
-case "$use_strategies" in
-?*' '?*)
- # Stash away the local changes so that we can try more than one.
- savestate
- single_strategy=no
- ;;
-*)
- rm -f "$GIT_DIR/MERGE_STASH"
- single_strategy=yes
- ;;
-esac
-
-result_tree= best_cnt=-1 best_strategy= wt_strategy=
-merge_was_ok=
-for strategy in $use_strategies
-do
- test "$wt_strategy" = '' || {
- echo "Rewinding the tree to pristine..."
- restorestate
- }
- case "$single_strategy" in
- no)
- echo "Trying merge strategy $strategy..."
- ;;
- esac
-
- # Remember which strategy left the state in the working tree
- wt_strategy=$strategy
-
- eval 'git-merge-$strategy '"$xopt"' $common -- "$head_arg" "$@"'
- exit=$?
- if test "$no_commit" = t && test "$exit" = 0
- then
- merge_was_ok=t
- exit=1 ;# pretend it left conflicts.
- fi
-
- test "$exit" = 0 || {
-
- # The backend exits with 1 when conflicts are left to be resolved,
- # with 2 when it does not handle the given merge at all.
-
- if test "$exit" -eq 1
- then
- cnt=$({
- git diff-files --name-only
- git ls-files --unmerged
- } | wc -l)
- if test $best_cnt -le 0 || test $cnt -le $best_cnt
- then
- best_strategy=$strategy
- best_cnt=$cnt
- fi
- fi
- continue
- }
-
- # Automerge succeeded.
- result_tree=$(git write-tree) && break
-done
-
-# If we have a resulting tree, that means the strategy module
-# auto resolved the merge cleanly.
-if test '' != "$result_tree"
-then
- if test "$allow_fast_forward" = "t"
- then
- parents=$(git merge-base --independent "$head" "$@")
- else
- parents=$(git rev-parse "$head" "$@")
- fi
- parents=$(echo "$parents" | sed -e 's/^/-p /')
- result_commit=$(printf '%s\n' "$merge_msg" | git commit-tree $result_tree $parents) || exit
- finish "$result_commit" "Merge made by $wt_strategy."
- dropsave
- exit 0
-fi
-
-# Pick the result from the best strategy and have the user fix it up.
-case "$best_strategy" in
-'')
- restorestate
- case "$use_strategies" in
- ?*' '?*)
- echo >&2 "No merge strategy handled the merge."
- ;;
- *)
- echo >&2 "Merge with strategy $use_strategies failed."
- ;;
- esac
- exit 2
- ;;
-"$wt_strategy")
- # We already have its result in the working tree.
- ;;
-*)
- echo "Rewinding the tree to pristine..."
- restorestate
- echo "Using the $best_strategy to prepare resolving by hand."
- git-merge-$best_strategy $common -- "$head_arg" "$@"
- ;;
-esac
-
-if test "$squash" = t
-then
- finish
-else
- for remote
- do
- echo $remote
- done >"$GIT_DIR/MERGE_HEAD"
- printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG" ||
- die "Could not write to $GIT_DIR/MERGE_MSG"
- if test "$allow_fast_forward" != t
- then
- printf "%s" no-ff
- else
- :
- fi >"$GIT_DIR/MERGE_MODE" ||
- die "Could not write to $GIT_DIR/MERGE_MODE"
-fi
-
-if test "$merge_was_ok" = t
-then
- echo >&2 \
- "Automatic merge went well; stopped before committing as requested"
- exit 0
-else
- {
- echo '
-Conflicts:
-'
- git ls-files --unmerged |
- sed -e 's/^[^ ]* / /' |
- uniq
- } >>"$GIT_DIR/MERGE_MSG"
- git rerere $rr_arg
- die "Automatic merge failed; fix conflicts and then commit the result."
-fi
+++ /dev/null
-#!/bin/sh
-
-USAGE="(edit [-F <file> | -m <msg>] | show) [commit]"
-. git-sh-setup
-
-test -z "$1" && usage
-ACTION="$1"; shift
-
-test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="$(git config core.notesref)"
-test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="refs/notes/commits"
-
-MESSAGE=
-while test $# != 0
-do
- case "$1" in
- -m)
- test "$ACTION" = "edit" || usage
- shift
- if test "$#" = "0"; then
- die "error: option -m needs an argument"
- else
- if [ -z "$MESSAGE" ]; then
- MESSAGE="$1"
- else
- MESSAGE="$MESSAGE
-
-$1"
- fi
- shift
- fi
- ;;
- -F)
- test "$ACTION" = "edit" || usage
- shift
- if test "$#" = "0"; then
- die "error: option -F needs an argument"
- else
- if [ -z "$MESSAGE" ]; then
- MESSAGE="$(cat "$1")"
- else
- MESSAGE="$MESSAGE
-
-$(cat "$1")"
- fi
- shift
- fi
- ;;
- -*)
- usage
- ;;
- *)
- break
- ;;
- esac
-done
-
-COMMIT=$(git rev-parse --verify --default HEAD "$@") ||
-die "Invalid commit: $@"
-
-case "$ACTION" in
-edit)
- if [ "${GIT_NOTES_REF#refs/notes/}" = "$GIT_NOTES_REF" ]; then
- die "Refusing to edit notes in $GIT_NOTES_REF (outside of refs/notes/)"
- fi
-
- MSG_FILE="$GIT_DIR/new-notes-$COMMIT"
- GIT_INDEX_FILE="$MSG_FILE.idx"
- export GIT_INDEX_FILE
-
- trap '
- test -f "$MSG_FILE" && rm "$MSG_FILE"
- test -f "$GIT_INDEX_FILE" && rm "$GIT_INDEX_FILE"
- ' 0
-
- CURRENT_HEAD=$(git show-ref "$GIT_NOTES_REF" | cut -f 1 -d ' ')
- if [ -z "$CURRENT_HEAD" ]; then
- PARENT=
- else
- PARENT="-p $CURRENT_HEAD"
- git read-tree "$GIT_NOTES_REF" || die "Could not read index"
- fi
-
- if [ -z "$MESSAGE" ]; then
- GIT_NOTES_REF= git log -1 $COMMIT | sed "s/^/#/" > "$MSG_FILE"
- if [ ! -z "$CURRENT_HEAD" ]; then
- git cat-file blob :$COMMIT >> "$MSG_FILE" 2> /dev/null
- fi
- core_editor="$(git config core.editor)"
- ${GIT_EDITOR:-${core_editor:-${VISUAL:-${EDITOR:-vi}}}} "$MSG_FILE"
- else
- echo "$MESSAGE" > "$MSG_FILE"
- fi
-
- grep -v ^# < "$MSG_FILE" | git stripspace > "$MSG_FILE".processed
- mv "$MSG_FILE".processed "$MSG_FILE"
- if [ -s "$MSG_FILE" ]; then
- BLOB=$(git hash-object -w "$MSG_FILE") ||
- die "Could not write into object database"
- git update-index --add --cacheinfo 0644 $BLOB $COMMIT ||
- die "Could not write index"
- else
- test -z "$CURRENT_HEAD" &&
- die "Will not initialise with empty tree"
- git update-index --force-remove $COMMIT ||
- die "Could not update index"
- fi
-
- TREE=$(git write-tree) || die "Could not write tree"
- NEW_HEAD=$(echo Annotate $COMMIT | git commit-tree $TREE $PARENT) ||
- die "Could not annotate"
- git update-ref -m "Annotate $COMMIT" \
- "$GIT_NOTES_REF" $NEW_HEAD $CURRENT_HEAD
-;;
-show)
- git rev-parse -q --verify "$GIT_NOTES_REF":$COMMIT > /dev/null ||
- die "No note for commit $COMMIT."
- git show "$GIT_NOTES_REF":$COMMIT
-;;
-*)
- usage
-esac
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Junio C Hamano
-#
-# Fetch one or more remote refs and merge it/them into the current HEAD.
-
-SUBDIRECTORY_OK=Yes
-OPTIONS_KEEPDASHDASH=
-OPTIONS_STUCKLONG=Yes
-OPTIONS_SPEC="\
-git pull [options] [<repository> [<refspec>...]]
-
-Fetch one or more remote refs and integrate it/them with the current HEAD.
---
-v,verbose be more verbose
-q,quiet be more quiet
-progress force progress reporting
-
- Options related to merging
-r,rebase?false|true|preserve incorporate changes by rebasing rather than merging
-n! do not show a diffstat at the end of the merge
-stat show a diffstat at the end of the merge
-summary (synonym to --stat)
-log?n add (at most <n>) entries from shortlog to merge commit message
-squash create a single commit instead of doing a merge
-commit perform a commit if the merge succeeds (default)
-e,edit edit message before committing
-ff allow fast-forward
-ff-only! abort if fast-forward is not possible
-verify-signatures verify that the named commit has a valid GPG signature
-s,strategy=strategy merge strategy to use
-X,strategy-option=option option for selected merge strategy
-S,gpg-sign?key-id GPG sign commit
-
- Options related to fetching
-all fetch from all remotes
-a,append append to .git/FETCH_HEAD instead of overwriting
-upload-pack=path path to upload pack on remote end
-f,force force overwrite of local branch
-t,tags fetch all tags and associated objects
-p,prune prune remote-tracking branches no longer on remote
-recurse-submodules?on-demand control recursive fetching of submodules
-dry-run dry run
-k,keep keep downloaded pack
-depth=depth deepen history of shallow clone
-unshallow convert to a complete repository
-update-shallow accept refs that update .git/shallow
-refmap=refmap specify fetch refmap
-"
-test $# -gt 0 && args="$*"
-. git-sh-setup
-. git-sh-i18n
-set_reflog_action "pull${args+ $args}"
-require_work_tree_exists
-cd_to_toplevel
-
-
-die_conflict () {
- git diff-index --cached --name-status -r --ignore-submodules HEAD --
- if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
- die "$(gettext "Pull is not possible because you have unmerged files.
-Please, fix them up in the work tree, and then use 'git add/rm <file>'
-as appropriate to mark resolution and make a commit.")"
- else
- die "$(gettext "Pull is not possible because you have unmerged files.")"
- fi
-}
-
-die_merge () {
- if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
- die "$(gettext "You have not concluded your merge (MERGE_HEAD exists).
-Please, commit your changes before merging.")"
- else
- die "$(gettext "You have not concluded your merge (MERGE_HEAD exists).")"
- fi
-}
-
-test -z "$(git ls-files -u)" || die_conflict
-test -f "$GIT_DIR/MERGE_HEAD" && die_merge
-
-bool_or_string_config () {
- git config --bool "$1" 2>/dev/null || git config "$1"
-}
-
-strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
-log_arg= verbosity= progress= recurse_submodules= verify_signatures=
-merge_args= edit= rebase_args= all= append= upload_pack= force= tags= prune=
-keep= depth= unshallow= update_shallow= refmap=
-curr_branch=$(git symbolic-ref -q HEAD)
-curr_branch_short="${curr_branch#refs/heads/}"
-rebase=$(bool_or_string_config branch.$curr_branch_short.rebase)
-if test -z "$rebase"
-then
- rebase=$(bool_or_string_config pull.rebase)
-fi
-
-# Setup default fast-forward options via `pull.ff`
-pull_ff=$(bool_or_string_config pull.ff)
-case "$pull_ff" in
-true)
- no_ff=--ff
- ;;
-false)
- no_ff=--no-ff
- ;;
-only)
- ff_only=--ff-only
- ;;
-esac
-
-
-dry_run=
-while :
-do
- case "$1" in
- -q|--quiet)
- verbosity="$verbosity -q" ;;
- -v|--verbose)
- verbosity="$verbosity -v" ;;
- --progress)
- progress=--progress ;;
- --no-progress)
- progress=--no-progress ;;
- -n|--no-stat|--no-summary)
- diffstat=--no-stat ;;
- --stat|--summary)
- diffstat=--stat ;;
- --log|--log=*|--no-log)
- log_arg="$1" ;;
- --no-commit)
- no_commit=--no-commit ;;
- --commit)
- no_commit=--commit ;;
- -e|--edit)
- edit=--edit ;;
- --no-edit)
- edit=--no-edit ;;
- --squash)
- squash=--squash ;;
- --no-squash)
- squash=--no-squash ;;
- --ff)
- no_ff=--ff ;;
- --no-ff)
- no_ff=--no-ff ;;
- --ff-only)
- ff_only=--ff-only ;;
- -s*|--strategy=*)
- strategy_args="$strategy_args $1"
- ;;
- -X*|--strategy-option=*)
- merge_args="$merge_args $(git rev-parse --sq-quote "$1")"
- ;;
- -r*|--rebase=*)
- rebase="${1#*=}"
- ;;
- --rebase)
- rebase=true
- ;;
- --no-rebase)
- rebase=false
- ;;
- --recurse-submodules)
- recurse_submodules=--recurse-submodules
- ;;
- --recurse-submodules=*)
- recurse_submodules="$1"
- ;;
- --no-recurse-submodules)
- recurse_submodules=--no-recurse-submodules
- ;;
- --verify-signatures)
- verify_signatures=--verify-signatures
- ;;
- --no-verify-signatures)
- verify_signatures=--no-verify-signatures
- ;;
- --gpg-sign|-S)
- gpg_sign_args=-S
- ;;
- --gpg-sign=*)
- gpg_sign_args=$(git rev-parse --sq-quote "-S${1#--gpg-sign=}")
- ;;
- -S*)
- gpg_sign_args=$(git rev-parse --sq-quote "$1")
- ;;
- --dry-run)
- dry_run=--dry-run
- ;;
- --all|--no-all)
- all=$1 ;;
- -a|--append|--no-append)
- append=$1 ;;
- --upload-pack=*|--no-upload-pack)
- upload_pack=$1 ;;
- -f|--force|--no-force)
- force="$force $1" ;;
- -t|--tags|--no-tags)
- tags=$1 ;;
- -p|--prune|--no-prune)
- prune=$1 ;;
- -k|--keep|--no-keep)
- keep=$1 ;;
- --depth=*|--no-depth)
- depth=$1 ;;
- --unshallow|--no-unshallow)
- unshallow=$1 ;;
- --update-shallow|--no-update-shallow)
- update_shallow=$1 ;;
- --refmap=*|--no-refmap)
- refmap=$1 ;;
- -h|--help-all)
- usage
- ;;
- --)
- shift
- break
- ;;
- *)
- usage
- ;;
- esac
- shift
-done
-
-case "$rebase" in
-preserve)
- rebase=true
- rebase_args=--preserve-merges
- ;;
-true|false|'')
- ;;
-*)
- echo "Invalid value for --rebase, should be true, false, or preserve"
- usage
- exit 1
- ;;
-esac
-
-error_on_no_merge_candidates () {
- exec >&2
-
- if test true = "$rebase"
- then
- op_type=rebase
- op_prep=against
- else
- op_type=merge
- op_prep=with
- fi
-
- upstream=$(git config "branch.$curr_branch_short.merge")
- remote=$(git config "branch.$curr_branch_short.remote")
-
- if [ $# -gt 1 ]; then
- if [ "$rebase" = true ]; then
- printf "There is no candidate for rebasing against "
- else
- printf "There are no candidates for merging "
- fi
- echo "among the refs that you just fetched."
- echo "Generally this means that you provided a wildcard refspec which had no"
- echo "matches on the remote end."
- elif [ $# -gt 0 ] && [ "$1" != "$remote" ]; then
- echo "You asked to pull from the remote '$1', but did not specify"
- echo "a branch. Because this is not the default configured remote"
- echo "for your current branch, you must specify a branch on the command line."
- elif [ -z "$curr_branch" -o -z "$upstream" ]; then
- . git-parse-remote
- error_on_missing_default_upstream "pull" $op_type $op_prep \
- "git pull <remote> <branch>"
- else
- echo "Your configuration specifies to $op_type $op_prep the ref '${upstream#refs/heads/}'"
- echo "from the remote, but no such ref was fetched."
- fi
- exit 1
-}
-
-test true = "$rebase" && {
- if ! git rev-parse -q --verify HEAD >/dev/null
- then
- # On an unborn branch
- if test -f "$(git rev-parse --git-path index)"
- then
- die "$(gettext "updating an unborn branch with changes added to the index")"
- fi
- else
- require_clean_work_tree "pull with rebase" "Please commit or stash them."
- fi
- oldremoteref= &&
- test -n "$curr_branch" &&
- . git-parse-remote &&
- remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
- oldremoteref=$(git merge-base --fork-point "$remoteref" $curr_branch 2>/dev/null)
-}
-orig_head=$(git rev-parse -q --verify HEAD)
-git fetch $verbosity $progress $dry_run $recurse_submodules $all $append \
-${upload_pack:+"$upload_pack"} $force $tags $prune $keep $depth $unshallow $update_shallow \
-$refmap --update-head-ok "$@" || exit 1
-test -z "$dry_run" || exit 0
-
-curr_head=$(git rev-parse -q --verify HEAD)
-if test -n "$orig_head" && test "$curr_head" != "$orig_head"
-then
- # The fetch involved updating the current branch.
-
- # The working tree and the index file is still based on the
- # $orig_head commit, but we are merging into $curr_head.
- # First update the working tree to match $curr_head.
-
- eval_gettextln "Warning: fetch updated the current branch head.
-Warning: fast-forwarding your working tree from
-Warning: commit \$orig_head." >&2
- git update-index -q --refresh
- git read-tree -u -m "$orig_head" "$curr_head" ||
- die "$(eval_gettext "Cannot fast-forward your working tree.
-After making sure that you saved anything precious from
-$ git diff \$orig_head
-output, run
-$ git reset --hard
-to recover.")"
-
-fi
-
-merge_head=$(sed -e '/ not-for-merge /d' \
- -e 's/ .*//' "$GIT_DIR"/FETCH_HEAD | \
- tr '\012' ' ')
-
-case "$merge_head" in
-'')
- error_on_no_merge_candidates "$@"
- ;;
-?*' '?*)
- if test -z "$orig_head"
- then
- die "$(gettext "Cannot merge multiple branches into empty head")"
- fi
- if test true = "$rebase"
- then
- die "$(gettext "Cannot rebase onto multiple branches")"
- fi
- ;;
-esac
-
-# Pulling into unborn branch: a shorthand for branching off
-# FETCH_HEAD, for lazy typers.
-if test -z "$orig_head"
-then
- # Two-way merge: we claim the index is based on an empty tree,
- # and try to fast-forward to HEAD. This ensures we will not
- # lose index/worktree changes that the user already made on
- # the unborn branch.
- empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
- git read-tree -m -u $empty_tree $merge_head &&
- git update-ref -m "initial pull" HEAD $merge_head "$curr_head"
- exit
-fi
-
-if test true = "$rebase"
-then
- o=$(git show-branch --merge-base $curr_branch $merge_head $oldremoteref)
- if test "$oldremoteref" = "$o"
- then
- unset oldremoteref
- fi
-fi
-
-case "$rebase" in
-true)
- eval="git-rebase $diffstat $strategy_args $merge_args $rebase_args $verbosity"
- eval="$eval $gpg_sign_args"
- eval="$eval --onto $merge_head ${oldremoteref:-$merge_head}"
- ;;
-*)
- eval="git-merge $diffstat $no_commit $verify_signatures $edit $squash $no_ff $ff_only"
- eval="$eval $log_arg $strategy_args $merge_args $verbosity $progress"
- eval="$eval $gpg_sign_args"
- eval="$eval FETCH_HEAD"
- ;;
-esac
-eval "exec $eval"
+++ /dev/null
-#!/usr/bin/perl -w
-
-use strict;
-use Git;
-my $git = Git->repository();
-
-sub add_remote_config {
- my ($hash, $name, $what, $value) = @_;
- if ($what eq 'url') {
- # Having more than one is Ok -- it is used for push.
- if (! exists $hash->{'URL'}) {
- $hash->{$name}{'URL'} = $value;
- }
- }
- elsif ($what eq 'fetch') {
- $hash->{$name}{'FETCH'} ||= [];
- push @{$hash->{$name}{'FETCH'}}, $value;
- }
- elsif ($what eq 'push') {
- $hash->{$name}{'PUSH'} ||= [];
- push @{$hash->{$name}{'PUSH'}}, $value;
- }
- if (!exists $hash->{$name}{'SOURCE'}) {
- $hash->{$name}{'SOURCE'} = 'config';
- }
-}
-
-sub add_remote_remotes {
- my ($hash, $file, $name) = @_;
-
- if (exists $hash->{$name}) {
- $hash->{$name}{'WARNING'} = 'ignored due to config';
- return;
- }
-
- my $fh;
- if (!open($fh, '<', $file)) {
- print STDERR "Warning: cannot open $file\n";
- return;
- }
- my $it = { 'SOURCE' => 'remotes' };
- $hash->{$name} = $it;
- while (<$fh>) {
- chomp;
- if (/^URL:\s*(.*)$/) {
- # Having more than one is Ok -- it is used for push.
- if (! exists $it->{'URL'}) {
- $it->{'URL'} = $1;
- }
- }
- elsif (/^Push:\s*(.*)$/) {
- $it->{'PUSH'} ||= [];
- push @{$it->{'PUSH'}}, $1;
- }
- elsif (/^Pull:\s*(.*)$/) {
- $it->{'FETCH'} ||= [];
- push @{$it->{'FETCH'}}, $1;
- }
- elsif (/^\#/) {
- ; # ignore
- }
- else {
- print STDERR "Warning: funny line in $file: $_\n";
- }
- }
- close($fh);
-}
-
-sub list_remote {
- my ($git) = @_;
- my %seen = ();
- my @remotes = eval {
- $git->command(qw(config --get-regexp), '^remote\.');
- };
- for (@remotes) {
- if (/^remote\.(\S+?)\.([^.\s]+)\s+(.*)$/) {
- add_remote_config(\%seen, $1, $2, $3);
- }
- }
-
- my $dir = $git->repo_path() . "/remotes";
- if (opendir(my $dh, $dir)) {
- local $_;
- while ($_ = readdir($dh)) {
- chomp;
- next if (! -f "$dir/$_" || ! -r _);
- add_remote_remotes(\%seen, "$dir/$_", $_);
- }
- }
-
- return \%seen;
-}
-
-sub add_branch_config {
- my ($hash, $name, $what, $value) = @_;
- if ($what eq 'remote') {
- if (exists $hash->{$name}{'REMOTE'}) {
- print STDERR "Warning: more than one branch.$name.remote\n";
- }
- $hash->{$name}{'REMOTE'} = $value;
- }
- elsif ($what eq 'merge') {
- $hash->{$name}{'MERGE'} ||= [];
- push @{$hash->{$name}{'MERGE'}}, $value;
- }
-}
-
-sub list_branch {
- my ($git) = @_;
- my %seen = ();
- my @branches = eval {
- $git->command(qw(config --get-regexp), '^branch\.');
- };
- for (@branches) {
- if (/^branch\.([^.]*)\.(\S*)\s+(.*)$/) {
- add_branch_config(\%seen, $1, $2, $3);
- }
- }
-
- return \%seen;
-}
-
-my $remote = list_remote($git);
-my $branch = list_branch($git);
-
-sub update_ls_remote {
- my ($harder, $info) = @_;
-
- return if (($harder == 0) ||
- (($harder == 1) && exists $info->{'LS_REMOTE'}));
-
- my @ref = map { s|refs/heads/||; $_; } keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
- $info->{'LS_REMOTE'} = \@ref;
-}
-
-sub list_wildcard_mapping {
- my ($forced, $ours, $ls) = @_;
- my %refs;
- for (@$ls) {
- $refs{$_} = 01; # bit #0 to say "they have"
- }
- for ($git->command('for-each-ref', "refs/remotes/$ours")) {
- chomp;
- next unless (s|^[0-9a-f]{40}\s[a-z]+\srefs/remotes/$ours/||);
- next if ($_ eq 'HEAD');
- $refs{$_} ||= 0;
- $refs{$_} |= 02; # bit #1 to say "we have"
- }
- my (@new, @stale, @tracked);
- for (sort keys %refs) {
- my $have = $refs{$_};
- if ($have == 1) {
- push @new, $_;
- }
- elsif ($have == 2) {
- push @stale, $_;
- }
- elsif ($have == 3) {
- push @tracked, $_;
- }
- }
- return \@new, \@stale, \@tracked;
-}
-
-sub list_mapping {
- my ($name, $info) = @_;
- my $fetch = $info->{'FETCH'};
- my $ls = $info->{'LS_REMOTE'};
- my (@new, @stale, @tracked);
-
- for (@$fetch) {
- next unless (/(\+)?([^:]+):(.*)/);
- my ($forced, $theirs, $ours) = ($1, $2, $3);
- if ($theirs eq 'refs/heads/*' &&
- $ours =~ /^refs\/remotes\/(.*)\/\*$/) {
- # wildcard mapping
- my ($w_new, $w_stale, $w_tracked)
- = list_wildcard_mapping($forced, $1, $ls);
- push @new, @$w_new;
- push @stale, @$w_stale;
- push @tracked, @$w_tracked;
- }
- elsif ($theirs =~ /\*/ || $ours =~ /\*/) {
- print STDERR "Warning: unrecognized mapping in remotes.$name.fetch: $_\n";
- }
- elsif ($theirs =~ s|^refs/heads/||) {
- if (!grep { $_ eq $theirs } @$ls) {
- push @stale, $theirs;
- }
- elsif ($ours ne '') {
- push @tracked, $theirs;
- }
- }
- }
- return \@new, \@stale, \@tracked;
-}
-
-sub show_mapping {
- my ($name, $info) = @_;
- my ($new, $stale, $tracked) = list_mapping($name, $info);
- if (@$new) {
- print " New remote branches (next fetch will store in remotes/$name)\n";
- print " @$new\n";
- }
- if (@$stale) {
- print " Stale tracking branches in remotes/$name (use 'git remote prune')\n";
- print " @$stale\n";
- }
- if (@$tracked) {
- print " Tracked remote branches\n";
- print " @$tracked\n";
- }
-}
-
-sub prune_remote {
- my ($name, $ls_remote) = @_;
- if (!exists $remote->{$name}) {
- print STDERR "No such remote $name\n";
- return 1;
- }
- my $info = $remote->{$name};
- update_ls_remote($ls_remote, $info);
-
- my ($new, $stale, $tracked) = list_mapping($name, $info);
- my $prefix = "refs/remotes/$name";
- foreach my $to_prune (@$stale) {
- my @v = $git->command(qw(rev-parse --verify), "$prefix/$to_prune");
- $git->command(qw(update-ref -d), "$prefix/$to_prune", $v[0]);
- }
- return 0;
-}
-
-sub show_remote {
- my ($name, $ls_remote) = @_;
- if (!exists $remote->{$name}) {
- print STDERR "No such remote $name\n";
- return 1;
- }
- my $info = $remote->{$name};
- update_ls_remote($ls_remote, $info);
-
- print "* remote $name\n";
- print " URL: $info->{'URL'}\n";
- for my $branchname (sort keys %$branch) {
- next unless (defined $branch->{$branchname}{'REMOTE'} &&
- $branch->{$branchname}{'REMOTE'} eq $name);
- my @merged = map {
- s|^refs/heads/||;
- $_;
- } split(' ',"@{$branch->{$branchname}{'MERGE'}}");
- next unless (@merged);
- print " Remote branch(es) merged with 'git pull' while on branch $branchname\n";
- print " @merged\n";
- }
- if ($info->{'LS_REMOTE'}) {
- show_mapping($name, $info);
- }
- if ($info->{'PUSH'}) {
- my @pushed = map {
- s|^refs/heads/||;
- s|^\+refs/heads/|+|;
- s|:refs/heads/|:|;
- $_;
- } @{$info->{'PUSH'}};
- print " Local branch(es) pushed with 'git push'\n";
- print " @pushed\n";
- }
- return 0;
-}
-
-sub add_remote {
- my ($name, $url, $opts) = @_;
- if (exists $remote->{$name}) {
- print STDERR "remote $name already exists.\n";
- exit(1);
- }
- $git->command('config', "remote.$name.url", $url);
- my $track = $opts->{'track'} || ["*"];
-
- for (@$track) {
- $git->command('config', '--add', "remote.$name.fetch",
- $opts->{'mirror'} ?
- "+refs/$_:refs/$_" :
- "+refs/heads/$_:refs/remotes/$name/$_");
- }
- if ($opts->{'fetch'}) {
- $git->command('fetch', $name);
- }
- if (exists $opts->{'master'}) {
- $git->command('symbolic-ref', "refs/remotes/$name/HEAD",
- "refs/remotes/$name/$opts->{'master'}");
- }
-}
-
-sub update_remote {
- my ($name) = @_;
- my @remotes;
-
- my $conf = $git->config("remotes." . $name);
- if (defined($conf)) {
- @remotes = split(' ', $conf);
- } elsif ($name eq 'default') {
- @remotes = ();
- for (sort keys %$remote) {
- my $do_fetch = $git->config_bool("remote." . $_ .
- ".skipDefaultUpdate");
- unless ($do_fetch) {
- push @remotes, $_;
- }
- }
- } else {
- print STDERR "Remote group $name does not exist.\n";
- exit(1);
- }
- for (@remotes) {
- print "Updating $_\n";
- $git->command('fetch', "$_");
- }
-}
-
-sub rm_remote {
- my ($name) = @_;
- if (!exists $remote->{$name}) {
- print STDERR "No such remote $name\n";
- return 1;
- }
-
- $git->command('config', '--remove-section', "remote.$name");
-
- eval {
- my @trackers = $git->command('config', '--get-regexp',
- 'branch.*.remote', $name);
- for (@trackers) {
- /^branch\.(.*)?\.remote/;
- $git->config('--unset', "branch.$1.remote");
- $git->config('--unset', "branch.$1.merge");
- }
- };
-
- my @refs = $git->command('for-each-ref',
- '--format=%(refname) %(objectname)', "refs/remotes/$name");
- for (@refs) {
- my ($ref, $object) = split;
- $git->command(qw(update-ref -d), $ref, $object);
- }
- return 0;
-}
-
-sub add_usage {
- print STDERR "usage: git remote add [-f] [-t track]* [-m master] <name> <url>\n";
- exit(1);
-}
-
-my $VERBOSE = 0;
-@ARGV = grep {
- if ($_ eq '-v' or $_ eq '--verbose') {
- $VERBOSE=1;
- 0
- } else {
- 1
- }
-} @ARGV;
-
-if (!@ARGV) {
- for (sort keys %$remote) {
- print "$_";
- print "\t$remote->{$_}->{URL}" if $VERBOSE;
- print "\n";
- }
-}
-elsif ($ARGV[0] eq 'show') {
- my $ls_remote = 1;
- my $i;
- for ($i = 1; $i < @ARGV; $i++) {
- if ($ARGV[$i] eq '-n') {
- $ls_remote = 0;
- }
- else {
- last;
- }
- }
- if ($i >= @ARGV) {
- print STDERR "usage: git remote show <remote>\n";
- exit(1);
- }
- my $status = 0;
- for (; $i < @ARGV; $i++) {
- $status |= show_remote($ARGV[$i], $ls_remote);
- }
- exit($status);
-}
-elsif ($ARGV[0] eq 'update') {
- if (@ARGV <= 1) {
- update_remote("default");
- exit(1);
- }
- for (my $i = 1; $i < @ARGV; $i++) {
- update_remote($ARGV[$i]);
- }
-}
-elsif ($ARGV[0] eq 'prune') {
- my $ls_remote = 1;
- my $i;
- for ($i = 1; $i < @ARGV; $i++) {
- if ($ARGV[$i] eq '-n') {
- $ls_remote = 0;
- }
- else {
- last;
- }
- }
- if ($i >= @ARGV) {
- print STDERR "usage: git remote prune <remote>\n";
- exit(1);
- }
- my $status = 0;
- for (; $i < @ARGV; $i++) {
- $status |= prune_remote($ARGV[$i], $ls_remote);
- }
- exit($status);
-}
-elsif ($ARGV[0] eq 'add') {
- my %opts = ();
- while (1 < @ARGV && $ARGV[1] =~ /^-/) {
- my $opt = $ARGV[1];
- shift @ARGV;
- if ($opt eq '-f' || $opt eq '--fetch') {
- $opts{'fetch'} = 1;
- next;
- }
- if ($opt eq '-t' || $opt eq '--track') {
- if (@ARGV < 1) {
- add_usage();
- }
- $opts{'track'} ||= [];
- push @{$opts{'track'}}, $ARGV[1];
- shift @ARGV;
- next;
- }
- if ($opt eq '-m' || $opt eq '--master') {
- if ((@ARGV < 1) || exists $opts{'master'}) {
- add_usage();
- }
- $opts{'master'} = $ARGV[1];
- shift @ARGV;
- next;
- }
- if ($opt eq '--mirror') {
- $opts{'mirror'} = 1;
- next;
- }
- add_usage();
- }
- if (@ARGV != 3) {
- add_usage();
- }
- add_remote($ARGV[1], $ARGV[2], \%opts);
-}
-elsif ($ARGV[0] eq 'rm') {
- if (@ARGV <= 1) {
- print STDERR "usage: git remote rm <remote>\n";
- exit(1);
- }
- exit(rm_remote($ARGV[1]));
-}
-else {
- print STDERR "usage: git remote\n";
- print STDERR " git remote add <name> <url>\n";
- print STDERR " git remote rm <name>\n";
- print STDERR " git remote show <name>\n";
- print STDERR " git remote prune <name>\n";
- print STDERR " git remote update [group]\n";
- exit(1);
-}
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC="\
-git repack [options]
---
-a pack everything in a single pack
-A same as -a, and turn unreachable objects loose
-d remove redundant packs, and run git-prune-packed
-f pass --no-reuse-delta to git-pack-objects
-F pass --no-reuse-object to git-pack-objects
-n do not run git-update-server-info
-q,quiet be quiet
-l pass --local to git-pack-objects
-unpack-unreachable= with -A, do not loosen objects older than this
- Packing constraints
-window= size of the window used for delta compression
-window-memory= same as the above, but limit memory size instead of entries count
-depth= limits the maximum delta depth
-max-pack-size= maximum size of each packfile
-"
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-no_update_info= all_into_one= remove_redundant= unpack_unreachable=
-local= no_reuse= extra=
-while test $# != 0
-do
- case "$1" in
- -n) no_update_info=t ;;
- -a) all_into_one=t ;;
- -A) all_into_one=t
- unpack_unreachable=--unpack-unreachable ;;
- --unpack-unreachable)
- unpack_unreachable="--unpack-unreachable=$2"; shift ;;
- -d) remove_redundant=t ;;
- -q) GIT_QUIET=t ;;
- -f) no_reuse=--no-reuse-delta ;;
- -F) no_reuse=--no-reuse-object ;;
- -l) local=--local ;;
- --max-pack-size|--window|--window-memory|--depth)
- extra="$extra $1=$2"; shift ;;
- --) shift; break;;
- *) usage ;;
- esac
- shift
-done
-
-case "$(git config --bool repack.usedeltabaseoffset || echo true)" in
-true)
- extra="$extra --delta-base-offset" ;;
-esac
-
-PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
-PACKTMP="$PACKDIR/.tmp-$$-pack"
-rm -f "$PACKTMP"-*
-trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
-
-# There will be more repacking strategies to come...
-case ",$all_into_one," in
-,,)
- args='--unpacked --incremental'
- ;;
-,t,)
- args= existing=
- if [ -d "$PACKDIR" ]; then
- for e in $(cd "$PACKDIR" && find . -type f -name '*.pack' \
- | sed -e 's/^\.\///' -e 's/\.pack$//')
- do
- if [ -e "$PACKDIR/$e.keep" ]; then
- : keep
- else
- existing="$existing $e"
- fi
- done
- if test -n "$existing" && test -n "$unpack_unreachable" && \
- test -n "$remove_redundant"
- then
- # This may have arbitrary user arguments, so we
- # have to protect it against whitespace splitting
- # when it gets run as "pack-objects $args" later.
- # Fortunately, we know it's an approxidate, so we
- # can just use dots instead.
- args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
- fi
- fi
- ;;
-esac
-
-mkdir -p "$PACKDIR" || exit
-
-args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
-names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
- exit 1
-if [ -z "$names" ]; then
- say Nothing new to pack.
-fi
-
-# Ok we have prepared all new packfiles.
-
-# First see if there are packs of the same name and if so
-# if we can move them out of the way (this can happen if we
-# repacked immediately after packing fully.
-rollback=
-failed=
-for name in $names
-do
- for sfx in pack idx
- do
- file=pack-$name.$sfx
- test -f "$PACKDIR/$file" || continue
- rm -f "$PACKDIR/old-$file" &&
- mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
- failed=t
- break
- }
- rollback="$rollback $file"
- done
- test -z "$failed" || break
-done
-
-# If renaming failed for any of them, roll the ones we have
-# already renamed back to their original names.
-if test -n "$failed"
-then
- rollback_failure=
- for file in $rollback
- do
- mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
- rollback_failure="$rollback_failure $file"
- done
- if test -n "$rollback_failure"
- then
- echo >&2 "WARNING: Some packs in use have been renamed by"
- echo >&2 "WARNING: prefixing old- to their name, in order to"
- echo >&2 "WARNING: replace them with the new version of the"
- echo >&2 "WARNING: file. But the operation failed, and"
- echo >&2 "WARNING: attempt to rename them back to their"
- echo >&2 "WARNING: original names also failed."
- echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
- for file in $rollback_failure
- do
- echo >&2 "WARNING: old-$file -> $file"
- done
- fi
- exit 1
-fi
-
-# Now the ones with the same name are out of the way...
-fullbases=
-for name in $names
-do
- fullbases="$fullbases pack-$name"
- chmod a-w "$PACKTMP-$name.pack"
- chmod a-w "$PACKTMP-$name.idx"
- mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
- mv -f "$PACKTMP-$name.idx" "$PACKDIR/pack-$name.idx" ||
- exit
-done
-
-# Remove the "old-" files
-for name in $names
-do
- rm -f "$PACKDIR/old-pack-$name.idx"
- rm -f "$PACKDIR/old-pack-$name.pack"
-done
-
-# End of pack replacement.
-
-if test "$remove_redundant" = t
-then
- # We know $existing are all redundant.
- if [ -n "$existing" ]
- then
- ( cd "$PACKDIR" &&
- for e in $existing
- do
- case " $fullbases " in
- *" $e "*) ;;
- *) rm -f "$e.pack" "$e.idx" "$e.keep" ;;
- esac
- done
- )
- fi
- git prune-packed ${GIT_QUIET:+-q}
-fi
-
-case "$no_update_info" in
-t) : ;;
-*) git update-server-info ;;
-esac
+++ /dev/null
-#!/usr/bin/perl
-#
-# REuse REcorded REsolve. This tool records a conflicted automerge
-# result and its hand resolution, and helps to resolve future
-# automerge that results in the same conflict.
-#
-# To enable this feature, create a directory 'rr-cache' under your
-# .git/ directory.
-
-use Digest;
-use File::Path;
-use File::Copy;
-
-my $git_dir = $::ENV{GIT_DIR} || ".git";
-my $rr_dir = "$git_dir/rr-cache";
-my $merge_rr = "$git_dir/rr-cache/MERGE_RR";
-
-my %merge_rr = ();
-
-sub read_rr {
- if (!-f $merge_rr) {
- %merge_rr = ();
- return;
- }
- my $in;
- local $/ = "\0";
- open $in, "<$merge_rr" or die "$!: $merge_rr";
- while (<$in>) {
- chomp;
- my ($name, $path) = /^([0-9a-f]{40})\t(.*)$/s;
- $merge_rr{$path} = $name;
- }
- close $in;
-}
-
-sub write_rr {
- my $out;
- open $out, ">$merge_rr" or die "$!: $merge_rr";
- for my $path (sort keys %merge_rr) {
- my $name = $merge_rr{$path};
- print $out "$name\t$path\0";
- }
- close $out;
-}
-
-sub compute_conflict_name {
- my ($path) = @_;
- my @side = ();
- my $in;
- open $in, "<$path" or die "$!: $path";
-
- my $sha1 = Digest->new("SHA-1");
- my $hunk = 0;
- while (<$in>) {
- if (/^<<<<<<< .*/) {
- $hunk++;
- @side = ([], undef);
- }
- elsif (/^=======$/) {
- $side[1] = [];
- }
- elsif (/^>>>>>>> .*/) {
- my ($one, $two);
- $one = join('', @{$side[0]});
- $two = join('', @{$side[1]});
- if ($two le $one) {
- ($one, $two) = ($two, $one);
- }
- $sha1->add($one);
- $sha1->add("\0");
- $sha1->add($two);
- $sha1->add("\0");
- @side = ();
- }
- elsif (@side == 0) {
- next;
- }
- elsif (defined $side[1]) {
- push @{$side[1]}, $_;
- }
- else {
- push @{$side[0]}, $_;
- }
- }
- close $in;
- return ($sha1->hexdigest, $hunk);
-}
-
-sub record_preimage {
- my ($path, $name) = @_;
- my @side = ();
- my ($in, $out);
- open $in, "<$path" or die "$!: $path";
- open $out, ">$name" or die "$!: $name";
-
- while (<$in>) {
- if (/^<<<<<<< .*/) {
- @side = ([], undef);
- }
- elsif (/^=======$/) {
- $side[1] = [];
- }
- elsif (/^>>>>>>> .*/) {
- my ($one, $two);
- $one = join('', @{$side[0]});
- $two = join('', @{$side[1]});
- if ($two le $one) {
- ($one, $two) = ($two, $one);
- }
- print $out "<<<<<<<\n";
- print $out $one;
- print $out "=======\n";
- print $out $two;
- print $out ">>>>>>>\n";
- @side = ();
- }
- elsif (@side == 0) {
- print $out $_;
- }
- elsif (defined $side[1]) {
- push @{$side[1]}, $_;
- }
- else {
- push @{$side[0]}, $_;
- }
- }
- close $out;
- close $in;
-}
-
-sub find_conflict {
- my $in;
- local $/ = "\0";
- my $pid = open($in, '-|');
- die "$!" unless defined $pid;
- if (!$pid) {
- exec(qw(git ls-files -z -u)) or die "$!: ls-files";
- }
- my %path = ();
- my @path = ();
- while (<$in>) {
- chomp;
- my ($mode, $sha1, $stage, $path) =
- /^([0-7]+) ([0-9a-f]{40}) ([123])\t(.*)$/s;
- $path{$path} |= (1 << $stage);
- }
- close $in;
- while (my ($path, $status) = each %path) {
- if ($status == 14) { push @path, $path; }
- }
- return @path;
-}
-
-sub merge {
- my ($name, $path) = @_;
- record_preimage($path, "$rr_dir/$name/thisimage");
- unless (system('git', 'merge-file', map { "$rr_dir/$name/${_}image" }
- qw(this pre post))) {
- my $in;
- open $in, "<$rr_dir/$name/thisimage" or
- die "$!: $name/thisimage";
- my $out;
- open $out, ">$path" or die "$!: $path";
- while (<$in>) { print $out $_; }
- close $in;
- close $out;
- return 1;
- }
- return 0;
-}
-
-sub garbage_collect_rerere {
- # We should allow specifying these from the command line and
- # that is why the caller gives @ARGV to us, but I am lazy.
-
- my $cutoff_noresolve = 15; # two weeks
- my $cutoff_resolve = 60; # two months
- my @to_remove;
- while (<$rr_dir/*/preimage>) {
- my ($dir) = /^(.*)\/preimage$/;
- my $cutoff = ((-f "$dir/postimage")
- ? $cutoff_resolve
- : $cutoff_noresolve);
- my $age = -M "$_";
- if ($cutoff <= $age) {
- push @to_remove, $dir;
- }
- }
- if (@to_remove) {
- rmtree(\@to_remove);
- }
-}
-
--d "$rr_dir" || exit(0);
-
-read_rr();
-
-if (@ARGV) {
- my $arg = shift @ARGV;
- if ($arg eq 'clear') {
- for my $path (keys %merge_rr) {
- my $name = $merge_rr{$path};
- if (-d "$rr_dir/$name" &&
- ! -f "$rr_dir/$name/postimage") {
- rmtree(["$rr_dir/$name"]);
- }
- }
- unlink $merge_rr;
- }
- elsif ($arg eq 'status') {
- for my $path (keys %merge_rr) {
- print $path, "\n";
- }
- }
- elsif ($arg eq 'diff') {
- for my $path (keys %merge_rr) {
- my $name = $merge_rr{$path};
- system('diff', ((@ARGV == 0) ? ('-u') : @ARGV),
- '-L', "a/$path", '-L', "b/$path",
- "$rr_dir/$name/preimage", $path);
- }
- }
- elsif ($arg eq 'gc') {
- garbage_collect_rerere(@ARGV);
- }
- else {
- die "$0 unknown command: $arg\n";
- }
- exit 0;
-}
-
-my %conflict = map { $_ => 1 } find_conflict();
-
-# MERGE_RR records paths with conflicts immediately after merge
-# failed. Some of the conflicted paths might have been hand resolved
-# in the working tree since then, but the initial run would catch all
-# and register their preimages.
-
-for my $path (keys %conflict) {
- # This path has conflict. If it is not recorded yet,
- # record the pre-image.
- if (!exists $merge_rr{$path}) {
- my ($name, $hunk) = compute_conflict_name($path);
- next unless ($hunk);
- $merge_rr{$path} = $name;
- if (! -d "$rr_dir/$name") {
- mkpath("$rr_dir/$name", 0, 0777);
- print STDERR "Recorded preimage for '$path'\n";
- record_preimage($path, "$rr_dir/$name/preimage");
- }
- }
-}
-
-# Now some of the paths that had conflicts earlier might have been
-# hand resolved. Others may be similar to a conflict already that
-# was resolved before.
-
-for my $path (keys %merge_rr) {
- my $name = $merge_rr{$path};
-
- # We could resolve this automatically if we have images.
- if (-f "$rr_dir/$name/preimage" &&
- -f "$rr_dir/$name/postimage") {
- if (merge($name, $path)) {
- print STDERR "Resolved '$path' using previous resolution.\n";
- # Then we do not have to worry about this path
- # anymore.
- delete $merge_rr{$path};
- next;
- }
- }
-
- # Let's see if we have resolved it.
- (undef, my $hunk) = compute_conflict_name($path);
- next if ($hunk);
-
- print STDERR "Recorded resolution for '$path'.\n";
- copy($path, "$rr_dir/$name/postimage");
- # And we do not have to worry about this path anymore.
- delete $merge_rr{$path};
-}
-
-# Write out the rest.
-write_rr();
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano
-#
-USAGE='[--mixed | --soft | --hard] [<commit-ish>] [ [--] <paths>...]'
-SUBDIRECTORY_OK=Yes
-. git-sh-setup
-set_reflog_action "reset $*"
-require_work_tree
-
-update= reset_type=--mixed
-unset rev
-
-while test $# != 0
-do
- case "$1" in
- --mixed | --soft | --hard)
- reset_type="$1"
- ;;
- --)
- break
- ;;
- -*)
- usage
- ;;
- *)
- rev=$(git rev-parse --verify "$1") || exit
- shift
- break
- ;;
- esac
- shift
-done
-
-: ${rev=HEAD}
-rev=$(git rev-parse --verify $rev^0) || exit
-
-# Skip -- in "git reset HEAD -- foo" and "git reset -- foo".
-case "$1" in --) shift ;; esac
-
-# git reset --mixed tree [--] paths... can be used to
-# load chosen paths from the tree into the index without
-# affecting the working tree or HEAD.
-if test $# != 0
-then
- test "$reset_type" = "--mixed" ||
- die "Cannot do partial $reset_type reset."
-
- git diff-index --cached $rev -- "$@" |
- sed -e 's/^:\([0-7][0-7]*\) [0-7][0-7]* \([0-9a-f][0-9a-f]*\) [0-9a-f][0-9a-f]* [A-Z] \(.*\)$/\1 \2 \3/' |
- git update-index --add --remove --index-info || exit
- git update-index --refresh
- exit
-fi
-
-cd_to_toplevel
-
-if test "$reset_type" = "--hard"
-then
- update=-u
-fi
-
-# Soft reset does not touch the index file or the working tree
-# at all, but requires them in a good order. Other resets reset
-# the index file to the tree object we are switching to.
-if test "$reset_type" = "--soft"
-then
- if test -f "$GIT_DIR/MERGE_HEAD" ||
- test "" != "$(git ls-files --unmerged)"
- then
- die "Cannot do a soft reset in the middle of a merge."
- fi
-else
- git read-tree -v --reset $update "$rev" || exit
-fi
-
-# Any resets update HEAD to the head being switched to.
-if orig=$(git rev-parse --verify HEAD 2>/dev/null)
-then
- echo "$orig" >"$GIT_DIR/ORIG_HEAD"
-else
- rm -f "$GIT_DIR/ORIG_HEAD"
-fi
-git update-ref -m "$GIT_REFLOG_ACTION" HEAD "$rev"
-update_ref_status=$?
-
-case "$reset_type" in
---hard )
- test $update_ref_status = 0 && {
- printf "HEAD is now at "
- GIT_PAGER= git log --max-count=1 --pretty=oneline \
- --abbrev-commit HEAD
- }
- ;;
---soft )
- ;; # Nothing else to do
---mixed )
- # Report what has not been updated.
- git update-index --refresh
- ;;
-esac
-
-rm -f "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/rr-cache/MERGE_RR" \
- "$GIT_DIR/SQUASH_MSG" "$GIT_DIR/MERGE_MSG"
-
-exit $update_ref_status
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-# Resolve two trees.
-#
-
-echo 'WARNING: This command is DEPRECATED and will be removed very soon.' >&2
-echo 'WARNING: Please use git-merge or git-pull instead.' >&2
-sleep 2
-
-USAGE='<head> <remote> <merge-message>'
-. git-sh-setup
-
-dropheads() {
- rm -f -- "$GIT_DIR/MERGE_HEAD" \
- "$GIT_DIR/LAST_MERGE" || exit 1
-}
-
-head=$(git rev-parse --verify "$1"^0) &&
-merge=$(git rev-parse --verify "$2"^0) &&
-merge_name="$2" &&
-merge_msg="$3" || usage
-
-#
-# The remote name is just used for the message,
-# but we do want it.
-#
-if [ -z "$head" -o -z "$merge" -o -z "$merge_msg" ]; then
- usage
-fi
-
-dropheads
-echo $head > "$GIT_DIR"/ORIG_HEAD
-echo $merge > "$GIT_DIR"/LAST_MERGE
-
-common=$(git merge-base $head $merge)
-if [ -z "$common" ]; then
- die "Unable to find common commit between" $merge $head
-fi
-
-case "$common" in
-"$merge")
- echo "Already up to date. Yeeah!"
- dropheads
- exit 0
- ;;
-"$head")
- echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $merge)"
- git read-tree -u -m $head $merge || exit 1
- git update-ref -m "resolve $merge_name: Fast-forward" \
- HEAD "$merge" "$head"
- git diff-tree -p $head $merge | git apply --stat
- dropheads
- exit 0
- ;;
-esac
-
-# We are going to make a new commit.
-git var GIT_COMMITTER_IDENT >/dev/null || exit
-
-# Find an optimum merge base if there are more than one candidates.
-LF='
-'
-common=$(git merge-base -a $head $merge)
-case "$common" in
-?*"$LF"?*)
- echo "Trying to find the optimum merge base."
- G=.tmp-index$$
- best=
- best_cnt=-1
- for c in $common
- do
- rm -f $G
- GIT_INDEX_FILE=$G git read-tree -m $c $head $merge \
- 2>/dev/null || continue
- # Count the paths that are unmerged.
- cnt=$(GIT_INDEX_FILE=$G git ls-files --unmerged | wc -l)
- if test $best_cnt -le 0 || test $cnt -le $best_cnt
- then
- best=$c
- best_cnt=$cnt
- if test "$best_cnt" -eq 0
- then
- # Cannot do any better than all trivial merge.
- break
- fi
- fi
- done
- rm -f $G
- common="$best"
-esac
-
-echo "Trying to merge $merge into $head using $common."
-git update-index --refresh 2>/dev/null
-git read-tree -u -m $common $head $merge || exit 1
-result_tree=$(git write-tree 2> /dev/null)
-if [ $? -ne 0 ]; then
- echo "Simple merge failed, trying Automatic merge"
- git-merge-index -o git-merge-one-file -a
- if [ $? -ne 0 ]; then
- echo $merge > "$GIT_DIR"/MERGE_HEAD
- die "Automatic merge failed, fix up by hand"
- fi
- result_tree=$(git write-tree) || exit 1
-fi
-result_commit=$(echo "$merge_msg" | git commit-tree $result_tree -p $head -p $merge)
-echo "Committed merge $result_commit"
-git update-ref -m "resolve $merge_name: In-index merge" \
- HEAD "$result_commit" "$head"
-git diff-tree -p $head $result_commit | git apply --stat
-dropheads
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-# Copyright (c) 2005 Junio C Hamano
-#
-
-case "$0" in
-*-revert* )
- test -t 0 && edit=-e
- replay=
- me=revert
- USAGE='[--edit | --no-edit] [-n] <commit-ish>' ;;
-*-cherry-pick* )
- replay=t
- edit=
- me=cherry-pick
- USAGE='[--edit] [-n] [-r] [-x] <commit-ish>' ;;
-* )
- echo >&2 "What are you talking about?"
- exit 1 ;;
-esac
-
-SUBDIRECTORY_OK=Yes ;# we will cd up
-. git-sh-setup
-require_work_tree
-cd_to_toplevel
-
-no_commit=
-xopt=
-while case "$#" in 0) break ;; esac
-do
- case "$1" in
- -n|--n|--no|--no-|--no-c|--no-co|--no-com|--no-comm|\
- --no-commi|--no-commit)
- no_commit=t
- ;;
- -e|--e|--ed|--edi|--edit)
- edit=-e
- ;;
- --n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit)
- edit=
- ;;
- -r)
- : no-op ;;
- -x|--i-really-want-to-expose-my-private-commit-object-name)
- replay=
- ;;
- -X?*)
- xopt="$xopt$(git rev-parse --sq-quote "--${1#-X}")"
- ;;
- --strategy-option=*)
- xopt="$xopt$(git rev-parse --sq-quote "--${1#--strategy-option=}")"
- ;;
- -X|--strategy-option)
- shift
- xopt="$xopt$(git rev-parse --sq-quote "--$1")"
- ;;
- -*)
- usage
- ;;
- *)
- break
- ;;
- esac
- shift
-done
-
-set_reflog_action "$me"
-
-test "$me,$replay" = "revert,t" && usage
-
-case "$no_commit" in
-t)
- # We do not intend to commit immediately. We just want to
- # merge the differences in.
- head=$(git-write-tree) ||
- die "Your index file is unmerged."
- ;;
-*)
- head=$(git-rev-parse --verify HEAD) ||
- die "You do not have a valid HEAD"
- files=$(git-diff-index --cached --name-only $head) || exit
- if [ "$files" ]; then
- die "Dirty index: cannot $me (dirty: $files)"
- fi
- ;;
-esac
-
-rev=$(git-rev-parse --verify "$@") &&
-commit=$(git-rev-parse --verify "$rev^0") ||
- die "Not a single commit $@"
-prev=$(git-rev-parse --verify "$commit^1" 2>/dev/null) ||
- die "Cannot run $me a root commit"
-git-rev-parse --verify "$commit^2" >/dev/null 2>&1 &&
- die "Cannot run $me a multi-parent commit."
-
-encoding=$(git config i18n.commitencoding || echo UTF-8)
-
-# "commit" is an existing commit. We would want to apply
-# the difference it introduces since its first parent "prev"
-# on top of the current HEAD if we are cherry-pick. Or the
-# reverse of it if we are revert.
-
-case "$me" in
-revert)
- git show -s --pretty=oneline --encoding="$encoding" $commit |
- sed -e '
- s/^[^ ]* /Revert "/
- s/$/"/
- '
- echo
- echo "This reverts commit $commit."
- test "$rev" = "$commit" ||
- echo "(original 'git revert' arguments: $@)"
- base=$commit next=$prev
- ;;
-
-cherry-pick)
- pick_author_script='
- /^author /{
- s/'\''/'\''\\'\'\''/g
- h
- s/^author \([^<]*\) <[^>]*> .*$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_NAME='\''&'\''/p
-
- g
- s/^author [^<]* <\([^>]*\)> .*$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
-
- g
- s/^author [^<]* <[^>]*> \(.*\)$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_DATE='\''&'\''/p
-
- q
- }'
-
- logmsg=$(git show -s --pretty=raw --encoding="$encoding" "$commit")
- set_author_env=$(echo "$logmsg" |
- LANG=C LC_ALL=C sed -ne "$pick_author_script")
- eval "$set_author_env"
- export GIT_AUTHOR_NAME
- export GIT_AUTHOR_EMAIL
- export GIT_AUTHOR_DATE
-
- echo "$logmsg" |
- sed -e '1,/^$/d' -e 's/^ //'
- case "$replay" in
- '')
- echo "(cherry picked from commit $commit)"
- test "$rev" = "$commit" ||
- echo "(original 'git cherry-pick' arguments: $@)"
- ;;
- esac
- base=$prev next=$commit
- ;;
-
-esac >.msg
-
-eval GITHEAD_$head=HEAD
-eval GITHEAD_$next='$(git show -s \
- --pretty=oneline --encoding="$encoding" "$commit" |
- sed -e "s/^[^ ]* //")'
-export GITHEAD_$head GITHEAD_$next
-
-# This three way merge is an interesting one. We are at
-# $head, and would want to apply the change between $commit
-# and $prev on top of us (when reverting), or the change between
-# $prev and $commit on top of us (when cherry-picking or replaying).
-
-eval "git merge-recursive $xopt $base -- $head $next" &&
-result=$(git-write-tree 2>/dev/null) || {
- mv -f .msg "$GIT_DIR/MERGE_MSG"
- {
- echo '
-Conflicts:
-'
- git ls-files --unmerged |
- sed -e 's/^[^ ]* / /' |
- uniq
- } >>"$GIT_DIR/MERGE_MSG"
- echo >&2 "Automatic $me failed. After resolving the conflicts,"
- echo >&2 "mark the corrected paths with 'git-add <paths>'"
- echo >&2 "and commit the result."
- case "$me" in
- cherry-pick)
- echo >&2 "You may choose to use the following when making"
- echo >&2 "the commit:"
- echo >&2 "$set_author_env"
- esac
- exit 1
-}
-
-# If we are cherry-pick, and if the merge did not result in
-# hand-editing, we will hit this commit and inherit the original
-# author date and name.
-# If we are revert, or if our cherry-pick results in a hand merge,
-# we had better say that the current user is responsible for that.
-
-case "$no_commit" in
-'')
- git-commit -n -F .msg $edit
- rm -f .msg
- ;;
-esac
+++ /dev/null
-#!/usr/bin/perl
-
-# This tool is copyright (c) 2005, Matthias Urlichs.
-# It is released under the Gnu Public License, version 2.
-#
-# The basic idea is to pull and analyze SVN changes.
-#
-# Checking out the files is done by a single long-running SVN connection.
-#
-# The head revision is on branch "origin" by default.
-# You can change that with the '-o' option.
-
-use strict;
-use warnings;
-use Getopt::Std;
-use File::Copy;
-use File::Spec;
-use File::Temp qw(tempfile);
-use File::Path qw(mkpath);
-use File::Basename qw(basename dirname);
-use Time::Local;
-use IO::Pipe;
-use POSIX qw(strftime dup2);
-use IPC::Open2;
-use SVN::Core;
-use SVN::Ra;
-
-die "Need SVN:Core 1.2.1 or better" if $SVN::Core::VERSION lt "1.2.1";
-
-$SIG{'PIPE'}="IGNORE";
-$ENV{'TZ'}="UTC";
-
-our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,
- $opt_b,$opt_r,$opt_I,$opt_A,$opt_s,$opt_l,$opt_d,$opt_D,$opt_S,$opt_F,
- $opt_P,$opt_R);
-
-sub usage() {
- print STDERR <<END;
-usage: ${\basename $0} # fetch/update GIT from SVN
- [-o branch-for-HEAD] [-h] [-v] [-l max_rev] [-R repack_each_revs]
- [-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
- [-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg]
- [-m] [-M regex] [-A author_file] [-S] [-F] [-P project_name] [SVN_URL]
-END
- exit(1);
-}
-
-getopts("A:b:C:dDFhiI:l:mM:o:rs:t:T:SP:R:uv") or usage();
-usage if $opt_h;
-
-my $tag_name = $opt_t || "tags";
-my $trunk_name = defined $opt_T ? $opt_T : "trunk";
-my $branch_name = $opt_b || "branches";
-my $project_name = $opt_P || "";
-$project_name = "/" . $project_name if ($project_name);
-my $repack_after = $opt_R || 1000;
-my $root_pool = SVN::Pool->new_default;
-
-@ARGV == 1 or @ARGV == 2 or usage();
-
-$opt_o ||= "origin";
-$opt_s ||= 1;
-my $git_tree = $opt_C;
-$git_tree ||= ".";
-
-my $svn_url = $ARGV[0];
-my $svn_dir = $ARGV[1];
-
-our @mergerx = ();
-if ($opt_m) {
- my $branch_esc = quotemeta ($branch_name);
- my $trunk_esc = quotemeta ($trunk_name);
- @mergerx =
- (
- qr!\b(?:merg(?:ed?|ing))\b.*?\b((?:(?<=$branch_esc/)[\w\.\-]+)|(?:$trunk_esc))\b!i,
- qr!\b(?:from|of)\W+((?:(?<=$branch_esc/)[\w\.\-]+)|(?:$trunk_esc))\b!i,
- qr!\b(?:from|of)\W+(?:the )?([\w\.\-]+)[-\s]branch\b!i
- );
-}
-if ($opt_M) {
- unshift (@mergerx, qr/$opt_M/);
-}
-
-# Absolutize filename now, since we will have chdir'ed by the time we
-# get around to opening it.
-$opt_A = File::Spec->rel2abs($opt_A) if $opt_A;
-
-our %users = ();
-our $users_file = undef;
-sub read_users($) {
- $users_file = File::Spec->rel2abs(@_);
- die "Cannot open $users_file\n" unless -f $users_file;
- open(my $authors,$users_file);
- while(<$authors>) {
- chomp;
- next unless /^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/;
- (my $user,my $name,my $email) = ($1,$2,$3);
- $users{$user} = [$name,$email];
- }
- close($authors);
-}
-
-select(STDERR); $|=1; select(STDOUT);
-
-
-package SVNconn;
-# Basic SVN connection.
-# We're only interested in connecting and downloading, so ...
-
-use File::Spec;
-use File::Temp qw(tempfile);
-use POSIX qw(strftime dup2);
-use Fcntl qw(SEEK_SET);
-
-sub new {
- my($what,$repo) = @_;
- $what=ref($what) if ref($what);
-
- my $self = {};
- $self->{'buffer'} = "";
- bless($self,$what);
-
- $repo =~ s#/+$##;
- $self->{'fullrep'} = $repo;
- $self->conn();
-
- return $self;
-}
-
-sub conn {
- my $self = shift;
- my $repo = $self->{'fullrep'};
- my $auth = SVN::Core::auth_open ([SVN::Client::get_simple_provider,
- SVN::Client::get_ssl_server_trust_file_provider,
- SVN::Client::get_username_provider]);
- my $s = SVN::Ra->new(url => $repo, auth => $auth, pool => $root_pool);
- die "SVN connection to $repo: $!\n" unless defined $s;
- $self->{'svn'} = $s;
- $self->{'repo'} = $repo;
- $self->{'maxrev'} = $s->get_latest_revnum();
-}
-
-sub file {
- my($self,$path,$rev) = @_;
-
- my ($fh, $name) = tempfile('gitsvn.XXXXXX',
- DIR => File::Spec->tmpdir(), UNLINK => 1);
-
- print "... $rev $path ...\n" if $opt_v;
- my (undef, $properties);
- $path =~ s#^/*##;
- my $subpool = SVN::Pool::new_default_sub;
- eval { (undef, $properties)
- = $self->{'svn'}->get_file($path,$rev,$fh); };
- if($@) {
- return undef if $@ =~ /Attempted to get checksum/;
- die $@;
- }
- my $mode;
- if (exists $properties->{'svn:executable'}) {
- $mode = '100755';
- } elsif (exists $properties->{'svn:special'}) {
- my ($special_content, $filesize);
- $filesize = tell $fh;
- seek $fh, 0, SEEK_SET;
- read $fh, $special_content, $filesize;
- if ($special_content =~ s/^link //) {
- $mode = '120000';
- seek $fh, 0, SEEK_SET;
- truncate $fh, 0;
- print $fh $special_content;
- } else {
- die "unexpected svn:special file encountered";
- }
- } else {
- $mode = '100644';
- }
- close ($fh);
-
- return ($name, $mode);
-}
-
-sub ignore {
- my($self,$path,$rev) = @_;
-
- print "... $rev $path ...\n" if $opt_v;
- $path =~ s#^/*##;
- my $subpool = SVN::Pool::new_default_sub;
- my (undef,undef,$properties)
- = $self->{'svn'}->get_dir($path,$rev,undef);
- if (exists $properties->{'svn:ignore'}) {
- my ($fh, $name) = tempfile('gitsvn.XXXXXX',
- DIR => File::Spec->tmpdir(),
- UNLINK => 1);
- print $fh $properties->{'svn:ignore'};
- close($fh);
- return $name;
- } else {
- return undef;
- }
-}
-
-sub dir_list {
- my($self,$path,$rev) = @_;
- $path =~ s#^/*##;
- my $subpool = SVN::Pool::new_default_sub;
- my ($dirents,undef,$properties)
- = $self->{'svn'}->get_dir($path,$rev,undef);
- return $dirents;
-}
-
-package main;
-use URI;
-
-our $svn = $svn_url;
-$svn .= "/$svn_dir" if defined $svn_dir;
-my $svn2 = SVNconn->new($svn);
-$svn = SVNconn->new($svn);
-
-my $lwp_ua;
-if($opt_d or $opt_D) {
- $svn_url = URI->new($svn_url)->canonical;
- if($opt_D) {
- $svn_dir =~ s#/*$#/#;
- } else {
- $svn_dir = "";
- }
- if ($svn_url->scheme eq "http") {
- use LWP::UserAgent;
- $lwp_ua = LWP::UserAgent->new(keep_alive => 1, requests_redirectable => []);
- } else {
- print STDERR "Warning: not HTTP; turning off direct file access\n";
- $opt_d=0;
- }
-}
-
-sub pdate($) {
- my($d) = @_;
- $d =~ m#(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)#
- or die "Unparseable date: $d\n";
- my $y=$1; $y+=1900 if $y<1000;
- return timegm($6||0,$5,$4,$3,$2-1,$y);
-}
-
-sub getwd() {
- my $pwd = `pwd`;
- chomp $pwd;
- return $pwd;
-}
-
-
-sub get_headref($$) {
- my $name = shift;
- my $git_dir = shift;
- my $sha;
-
- if (open(C,"$git_dir/refs/heads/$name")) {
- chomp($sha = <C>);
- close(C);
- length($sha) == 40
- or die "Cannot get head id for $name ($sha): $!\n";
- }
- return $sha;
-}
-
-
--d $git_tree
- or mkdir($git_tree,0777)
- or die "Could not create $git_tree: $!";
-chdir($git_tree);
-
-my $orig_branch = "";
-my $forward_master = 0;
-my %branches;
-
-my $git_dir = $ENV{"GIT_DIR"} || ".git";
-$git_dir = getwd()."/".$git_dir unless $git_dir =~ m#^/#;
-$ENV{"GIT_DIR"} = $git_dir;
-my $orig_git_index;
-$orig_git_index = $ENV{GIT_INDEX_FILE} if exists $ENV{GIT_INDEX_FILE};
-my ($git_ih, $git_index) = tempfile('gitXXXXXX', SUFFIX => '.idx',
- DIR => File::Spec->tmpdir());
-close ($git_ih);
-$ENV{GIT_INDEX_FILE} = $git_index;
-my $maxnum = 0;
-my $last_rev = "";
-my $last_branch;
-my $current_rev = $opt_s || 1;
-unless(-d $git_dir) {
- system("git init");
- die "Cannot init the GIT db at $git_tree: $?\n" if $?;
- system("git read-tree --empty");
- die "Cannot init an empty tree: $?\n" if $?;
-
- $last_branch = $opt_o;
- $orig_branch = "";
-} else {
- -f "$git_dir/refs/heads/$opt_o"
- or die "Branch '$opt_o' does not exist.\n".
- "Either use the correct '-o branch' option,\n".
- "or import to a new repository.\n";
-
- -f "$git_dir/svn2git"
- or die "'$git_dir/svn2git' does not exist.\n".
- "You need that file for incremental imports.\n";
- open(F, "git symbolic-ref HEAD |") or
- die "Cannot run git-symbolic-ref: $!\n";
- chomp ($last_branch = <F>);
- $last_branch = basename($last_branch);
- close(F);
- unless($last_branch) {
- warn "Cannot read the last branch name: $! -- assuming 'master'\n";
- $last_branch = "master";
- }
- $orig_branch = $last_branch;
- $last_rev = get_headref($orig_branch, $git_dir);
- if (-f "$git_dir/SVN2GIT_HEAD") {
- die <<EOM;
-SVN2GIT_HEAD exists.
-Make sure your working directory corresponds to HEAD and remove SVN2GIT_HEAD.
-You may need to run
-
- git-read-tree -m -u SVN2GIT_HEAD HEAD
-EOM
- }
- system('cp', "$git_dir/HEAD", "$git_dir/SVN2GIT_HEAD");
-
- $forward_master =
- $opt_o ne 'master' && -f "$git_dir/refs/heads/master" &&
- system('cmp', '-s', "$git_dir/refs/heads/master",
- "$git_dir/refs/heads/$opt_o") == 0;
-
- # populate index
- system('git', 'read-tree', $last_rev);
- die "read-tree failed: $?\n" if $?;
-
- # Get the last import timestamps
- open my $B,"<", "$git_dir/svn2git";
- while(<$B>) {
- chomp;
- my($num,$branch,$ref) = split;
- $branches{$branch}{$num} = $ref;
- $branches{$branch}{"LAST"} = $ref;
- $current_rev = $num+1 if $current_rev <= $num;
- }
- close($B);
-}
--d $git_dir
- or die "Could not create git subdir ($git_dir).\n";
-
-my $default_authors = "$git_dir/svn-authors";
-if ($opt_A) {
- read_users($opt_A);
- copy($opt_A,$default_authors) or die "Copy failed: $!";
-} else {
- read_users($default_authors) if -f $default_authors;
-}
-
-open BRANCHES,">>", "$git_dir/svn2git";
-
-sub node_kind($$) {
- my ($svnpath, $revision) = @_;
- $svnpath =~ s#^/*##;
- my $subpool = SVN::Pool::new_default_sub;
- my $kind = $svn->{'svn'}->check_path($svnpath,$revision);
- return $kind;
-}
-
-sub get_file($$$) {
- my($svnpath,$rev,$path) = @_;
-
- # now get it
- my ($name,$mode);
- if($opt_d) {
- my($req,$res);
-
- # /svn/!svn/bc/2/django/trunk/django-docs/build.py
- my $url=$svn_url->clone();
- $url->path($url->path."/!svn/bc/$rev/$svn_dir$svnpath");
- print "... $path...\n" if $opt_v;
- $req = HTTP::Request->new(GET => $url);
- $res = $lwp_ua->request($req);
- if ($res->is_success) {
- my $fh;
- ($fh, $name) = tempfile('gitsvn.XXXXXX',
- DIR => File::Spec->tmpdir(), UNLINK => 1);
- print $fh $res->content;
- close($fh) or die "Could not write $name: $!\n";
- } else {
- return undef if $res->code == 301; # directory?
- die $res->status_line." at $url\n";
- }
- $mode = '0644'; # can't obtain mode via direct http request?
- } else {
- ($name,$mode) = $svn->file("$svnpath",$rev);
- return undef unless defined $name;
- }
-
- my $pid = open(my $F, '-|');
- die $! unless defined $pid;
- if (!$pid) {
- exec("git", "hash-object", "-w", $name)
- or die "Cannot create object: $!\n";
- }
- my $sha = <$F>;
- chomp $sha;
- close $F;
- unlink $name;
- return [$mode, $sha, $path];
-}
-
-sub get_ignore($$$$$) {
- my($new,$old,$rev,$path,$svnpath) = @_;
-
- return unless $opt_I;
- my $name = $svn->ignore("$svnpath",$rev);
- if ($path eq '/') {
- $path = $opt_I;
- } else {
- $path = File::Spec->catfile($path,$opt_I);
- }
- if (defined $name) {
- my $pid = open(my $F, '-|');
- die $! unless defined $pid;
- if (!$pid) {
- exec("git", "hash-object", "-w", $name)
- or die "Cannot create object: $!\n";
- }
- my $sha = <$F>;
- chomp $sha;
- close $F;
- unlink $name;
- push(@$new,['0644',$sha,$path]);
- } elsif (defined $old) {
- push(@$old,$path);
- }
-}
-
-sub project_path($$)
-{
- my ($path, $project) = @_;
-
- $path = "/".$path unless ($path =~ m#^\/#) ;
- return $1 if ($path =~ m#^$project\/(.*)$#);
-
- $path =~ s#\.#\\\.#g;
- $path =~ s#\+#\\\+#g;
- return "/" if ($project =~ m#^$path.*$#);
-
- return undef;
-}
-
-sub split_path($$) {
- my($rev,$path) = @_;
- my $branch;
-
- if($path =~ s#^/\Q$tag_name\E/([^/]+)/?##) {
- $branch = "/$1";
- } elsif($path =~ s#^/\Q$trunk_name\E/?##) {
- $branch = "/";
- } elsif($path =~ s#^/\Q$branch_name\E/([^/]+)/?##) {
- $branch = $1;
- } else {
- my %no_error = (
- "/" => 1,
- "/$tag_name" => 1,
- "/$branch_name" => 1
- );
- print STDERR "$rev: Unrecognized path: $path\n" unless (defined $no_error{$path});
- return ()
- }
- if ($path eq "") {
- $path = "/";
- } elsif ($project_name) {
- $path = project_path($path, $project_name);
- }
- return ($branch,$path);
-}
-
-sub branch_rev($$) {
-
- my ($srcbranch,$uptorev) = @_;
-
- my $bbranches = $branches{$srcbranch};
- my @revs = reverse sort { ($a eq 'LAST' ? 0 : $a) <=> ($b eq 'LAST' ? 0 : $b) } keys %$bbranches;
- my $therev;
- foreach my $arev(@revs) {
- next if ($arev eq 'LAST');
- if ($arev <= $uptorev) {
- $therev = $arev;
- last;
- }
- }
- return $therev;
-}
-
-sub expand_svndir($$$);
-
-sub expand_svndir($$$)
-{
- my ($svnpath, $rev, $path) = @_;
- my @list;
- get_ignore(\@list, undef, $rev, $path, $svnpath);
- my $dirents = $svn->dir_list($svnpath, $rev);
- foreach my $p(keys %$dirents) {
- my $kind = node_kind($svnpath.'/'.$p, $rev);
- if ($kind eq $SVN::Node::file) {
- my $f = get_file($svnpath.'/'.$p, $rev, $path.'/'.$p);
- push(@list, $f) if $f;
- } elsif ($kind eq $SVN::Node::dir) {
- push(@list,
- expand_svndir($svnpath.'/'.$p, $rev, $path.'/'.$p));
- }
- }
- return @list;
-}
-
-sub copy_path($$$$$$$$) {
- # Somebody copied a whole subdirectory.
- # We need to find the index entries from the old version which the
- # SVN log entry points to, and add them to the new place.
-
- my($newrev,$newbranch,$path,$oldpath,$rev,$node_kind,$new,$parents) = @_;
-
- my($srcbranch,$srcpath) = split_path($rev,$oldpath);
- unless(defined $srcbranch && defined $srcpath) {
- print "Path not found when copying from $oldpath @ $rev.\n".
- "Will try to copy from original SVN location...\n"
- if $opt_v;
- push (@$new, expand_svndir($oldpath, $rev, $path));
- return;
- }
- my $therev = branch_rev($srcbranch, $rev);
- my $gitrev = $branches{$srcbranch}{$therev};
- unless($gitrev) {
- print STDERR "$newrev:$newbranch: could not find $oldpath \@ $rev\n";
- return;
- }
- if ($srcbranch ne $newbranch) {
- push(@$parents, $branches{$srcbranch}{'LAST'});
- }
- print "$newrev:$newbranch:$path: copying from $srcbranch:$srcpath @ $rev\n" if $opt_v;
- if ($node_kind eq $SVN::Node::dir) {
- $srcpath =~ s#/*$#/#;
- }
-
- my $pid = open my $f,'-|';
- die $! unless defined $pid;
- if (!$pid) {
- exec("git","ls-tree","-r","-z",$gitrev,$srcpath)
- or die $!;
- }
- local $/ = "\0";
- while(<$f>) {
- chomp;
- my($m,$p) = split(/\t/,$_,2);
- my($mode,$type,$sha1) = split(/ /,$m);
- next if $type ne "blob";
- if ($node_kind eq $SVN::Node::dir) {
- $p = $path . substr($p,length($srcpath)-1);
- } else {
- $p = $path;
- }
- push(@$new,[$mode,$sha1,$p]);
- }
- close($f) or
- print STDERR "$newrev:$newbranch: could not list files in $oldpath \@ $rev\n";
-}
-
-sub commit {
- my($branch, $changed_paths, $revision, $author, $date, $message) = @_;
- my($committer_name,$committer_email,$dest);
- my($author_name,$author_email);
- my(@old,@new,@parents);
-
- if (not defined $author or $author eq "") {
- $committer_name = $committer_email = "unknown";
- } elsif (defined $users_file) {
- die "User $author is not listed in $users_file\n"
- unless exists $users{$author};
- ($committer_name,$committer_email) = @{$users{$author}};
- } elsif ($author =~ /^(.*?)\s+<(.*)>$/) {
- ($committer_name, $committer_email) = ($1, $2);
- } else {
- $author =~ s/^<(.*)>$/$1/;
- $committer_name = $committer_email = $author;
- }
-
- if ($opt_F && $message =~ /From:\s+(.*?)\s+<(.*)>\s*\n/) {
- ($author_name, $author_email) = ($1, $2);
- print "Author from From: $1 <$2>\n" if ($opt_v);;
- } elsif ($opt_S && $message =~ /Signed-off-by:\s+(.*?)\s+<(.*)>\s*\n/) {
- ($author_name, $author_email) = ($1, $2);
- print "Author from Signed-off-by: $1 <$2>\n" if ($opt_v);;
- } else {
- $author_name = $committer_name;
- $author_email = $committer_email;
- }
-
- $date = pdate($date);
-
- my $tag;
- my $parent;
- if($branch eq "/") { # trunk
- $parent = $opt_o;
- } elsif($branch =~ m#^/(.+)#) { # tag
- $tag = 1;
- $parent = $1;
- } else { # "normal" branch
- # nothing to do
- $parent = $branch;
- }
- $dest = $parent;
-
- my $prev = $changed_paths->{"/"};
- if($prev and $prev->[0] eq "A") {
- delete $changed_paths->{"/"};
- my $oldpath = $prev->[1];
- my $rev;
- if(defined $oldpath) {
- my $p;
- ($parent,$p) = split_path($revision,$oldpath);
- if(defined $parent) {
- if($parent eq "/") {
- $parent = $opt_o;
- } else {
- $parent =~ s#^/##; # if it's a tag
- }
- }
- } else {
- $parent = undef;
- }
- }
-
- my $rev;
- if($revision > $opt_s and defined $parent) {
- open(H,'-|',"git","rev-parse","--verify",$parent);
- $rev = <H>;
- close(H) or do {
- print STDERR "$revision: cannot find commit '$parent'!\n";
- return;
- };
- chop $rev;
- if(length($rev) != 40) {
- print STDERR "$revision: cannot find commit '$parent'!\n";
- return;
- }
- $rev = $branches{($parent eq $opt_o) ? "/" : $parent}{"LAST"};
- if($revision != $opt_s and not $rev) {
- print STDERR "$revision: do not know ancestor for '$parent'!\n";
- return;
- }
- } else {
- $rev = undef;
- }
-
-# if($prev and $prev->[0] eq "A") {
-# if(not $tag) {
-# unless(open(H,"> $git_dir/refs/heads/$branch")) {
-# print STDERR "$revision: Could not create branch $branch: $!\n";
-# $state=11;
-# next;
-# }
-# print H "$rev\n"
-# or die "Could not write branch $branch: $!";
-# close(H)
-# or die "Could not write branch $branch: $!";
-# }
-# }
- if(not defined $rev) {
- unlink($git_index);
- } elsif ($rev ne $last_rev) {
- print "Switching from $last_rev to $rev ($branch)\n" if $opt_v;
- system("git", "read-tree", $rev);
- die "read-tree failed for $rev: $?\n" if $?;
- $last_rev = $rev;
- }
-
- push (@parents, $rev) if defined $rev;
-
- my $cid;
- if($tag and not %$changed_paths) {
- $cid = $rev;
- } else {
- my @paths = sort keys %$changed_paths;
- foreach my $path(@paths) {
- my $action = $changed_paths->{$path};
-
- if ($action->[0] eq "R") {
- # refer to a file/tree in an earlier commit
- push(@old,$path); # remove any old stuff
- }
- if(($action->[0] eq "A") || ($action->[0] eq "R")) {
- my $node_kind = node_kind($action->[3], $revision);
- if ($node_kind eq $SVN::Node::file) {
- my $f = get_file($action->[3],
- $revision, $path);
- if ($f) {
- push(@new,$f) if $f;
- } else {
- my $opath = $action->[3];
- print STDERR "$revision: $branch: could not fetch '$opath'\n";
- }
- } elsif ($node_kind eq $SVN::Node::dir) {
- if($action->[1]) {
- copy_path($revision, $branch,
- $path, $action->[1],
- $action->[2], $node_kind,
- \@new, \@parents);
- } else {
- get_ignore(\@new, \@old, $revision,
- $path, $action->[3]);
- }
- }
- } elsif ($action->[0] eq "D") {
- push(@old,$path);
- } elsif ($action->[0] eq "M") {
- my $node_kind = node_kind($action->[3], $revision);
- if ($node_kind eq $SVN::Node::file) {
- my $f = get_file($action->[3],
- $revision, $path);
- push(@new,$f) if $f;
- } elsif ($node_kind eq $SVN::Node::dir) {
- get_ignore(\@new, \@old, $revision,
- $path, $action->[3]);
- }
- } else {
- die "$revision: unknown action '".$action->[0]."' for $path\n";
- }
- }
-
- while(@old) {
- my @o1;
- if(@old > 55) {
- @o1 = splice(@old,0,50);
- } else {
- @o1 = @old;
- @old = ();
- }
- my $pid = open my $F, "-|";
- die "$!" unless defined $pid;
- if (!$pid) {
- exec("git", "ls-files", "-z", @o1) or die $!;
- }
- @o1 = ();
- local $/ = "\0";
- while(<$F>) {
- chomp;
- push(@o1,$_);
- }
- close($F);
-
- while(@o1) {
- my @o2;
- if(@o1 > 55) {
- @o2 = splice(@o1,0,50);
- } else {
- @o2 = @o1;
- @o1 = ();
- }
- system("git","update-index","--force-remove","--",@o2);
- die "Cannot remove files: $?\n" if $?;
- }
- }
- while(@new) {
- my @n2;
- if(@new > 12) {
- @n2 = splice(@new,0,10);
- } else {
- @n2 = @new;
- @new = ();
- }
- system("git","update-index","--add",
- (map { ('--cacheinfo', @$_) } @n2));
- die "Cannot add files: $?\n" if $?;
- }
-
- my $pid = open(C,"-|");
- die "Cannot fork: $!" unless defined $pid;
- unless($pid) {
- exec("git","write-tree");
- die "Cannot exec git-write-tree: $!\n";
- }
- chomp(my $tree = <C>);
- length($tree) == 40
- or die "Cannot get tree id ($tree): $!\n";
- close(C)
- or die "Error running git-write-tree: $?\n";
- print "Tree ID $tree\n" if $opt_v;
-
- my $pr = IO::Pipe->new() or die "Cannot open pipe: $!\n";
- my $pw = IO::Pipe->new() or die "Cannot open pipe: $!\n";
- $pid = fork();
- die "Fork: $!\n" unless defined $pid;
- unless($pid) {
- $pr->writer();
- $pw->reader();
- open(OUT,">&STDOUT");
- dup2($pw->fileno(),0);
- dup2($pr->fileno(),1);
- $pr->close();
- $pw->close();
-
- my @par = ();
-
- # loose detection of merges
- # based on the commit msg
- foreach my $rx (@mergerx) {
- if ($message =~ $rx) {
- my $mparent = $1;
- if ($mparent eq 'HEAD') { $mparent = $opt_o };
- if ( -e "$git_dir/refs/heads/$mparent") {
- $mparent = get_headref($mparent, $git_dir);
- push (@parents, $mparent);
- print OUT "Merge parent branch: $mparent\n" if $opt_v;
- }
- }
- }
- my %seen_parents = ();
- my @unique_parents = grep { ! $seen_parents{$_} ++ } @parents;
- foreach my $bparent (@unique_parents) {
- push @par, '-p', $bparent;
- print OUT "Merge parent branch: $bparent\n" if $opt_v;
- }
-
- exec("env",
- "GIT_AUTHOR_NAME=$author_name",
- "GIT_AUTHOR_EMAIL=$author_email",
- "GIT_AUTHOR_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)),
- "GIT_COMMITTER_NAME=$committer_name",
- "GIT_COMMITTER_EMAIL=$committer_email",
- "GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)),
- "git", "commit-tree", $tree,@par);
- die "Cannot exec git-commit-tree: $!\n";
- }
- $pw->writer();
- $pr->reader();
-
- $message =~ s/[\s\n]+\z//;
- $message = "r$revision: $message" if $opt_r;
-
- print $pw "$message\n"
- or die "Error writing to git-commit-tree: $!\n";
- $pw->close();
-
- print "Committed change $revision:$branch ".strftime("%Y-%m-%d %H:%M:%S",gmtime($date)).")\n" if $opt_v;
- chomp($cid = <$pr>);
- length($cid) == 40
- or die "Cannot get commit id ($cid): $!\n";
- print "Commit ID $cid\n" if $opt_v;
- $pr->close();
-
- waitpid($pid,0);
- die "Error running git-commit-tree: $?\n" if $?;
- }
-
- if (not defined $cid) {
- $cid = $branches{"/"}{"LAST"};
- }
-
- if(not defined $dest) {
- print "... no known parent\n" if $opt_v;
- } elsif(not $tag) {
- print "Writing to refs/heads/$dest\n" if $opt_v;
- open(C,">$git_dir/refs/heads/$dest") and
- print C ("$cid\n") and
- close(C)
- or die "Cannot write branch $dest for update: $!\n";
- }
-
- if ($tag) {
- $last_rev = "-" if %$changed_paths;
- # the tag was 'complex', i.e. did not refer to a "real" revision
-
- $dest =~ tr/_/\./ if $opt_u;
-
- system('git', 'tag', '-f', $dest, $cid) == 0
- or die "Cannot create tag $dest: $!\n";
-
- print "Created tag '$dest' on '$branch'\n" if $opt_v;
- }
- $branches{$branch}{"LAST"} = $cid;
- $branches{$branch}{$revision} = $cid;
- $last_rev = $cid;
- print BRANCHES "$revision $branch $cid\n";
- print "DONE: $revision $dest $cid\n" if $opt_v;
-}
-
-sub commit_all {
- # Recursive use of the SVN connection does not work
- local $svn = $svn2;
-
- my ($changed_paths, $revision, $author, $date, $message) = @_;
- my %p;
- while(my($path,$action) = each %$changed_paths) {
- $p{$path} = [ $action->action,$action->copyfrom_path, $action->copyfrom_rev, $path ];
- }
- $changed_paths = \%p;
-
- my %done;
- my @col;
- my $pref;
- my $branch;
-
- while(my($path,$action) = each %$changed_paths) {
- ($branch,$path) = split_path($revision,$path);
- next if not defined $branch;
- next if not defined $path;
- $done{$branch}{$path} = $action;
- }
- while(($branch,$changed_paths) = each %done) {
- commit($branch, $changed_paths, $revision, $author, $date, $message);
- }
-}
-
-$opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'};
-
-if ($opt_l < $current_rev) {
- print "Up to date: no new revisions to fetch!\n" if $opt_v;
- unlink("$git_dir/SVN2GIT_HEAD");
- exit;
-}
-
-print "Processing from $current_rev to $opt_l ...\n" if $opt_v;
-
-my $from_rev;
-my $to_rev = $current_rev - 1;
-
-my $subpool = SVN::Pool::new_default_sub;
-while ($to_rev < $opt_l) {
- $subpool->clear;
- $from_rev = $to_rev + 1;
- $to_rev = $from_rev + $repack_after;
- $to_rev = $opt_l if $opt_l < $to_rev;
- print "Fetching from $from_rev to $to_rev ...\n" if $opt_v;
- $svn->{'svn'}->get_log("",$from_rev,$to_rev,0,1,1,\&commit_all);
- my $pid = fork();
- die "Fork: $!\n" unless defined $pid;
- unless($pid) {
- exec("git", "repack", "-d")
- or die "Cannot repack: $!\n";
- }
- waitpid($pid, 0);
-}
-
-
-unlink($git_index);
-
-if (defined $orig_git_index) {
- $ENV{GIT_INDEX_FILE} = $orig_git_index;
-} else {
- delete $ENV{GIT_INDEX_FILE};
-}
-
-# Now switch back to the branch we were in before all of this happened
-if($orig_branch) {
- print "DONE\n" if $opt_v and (not defined $opt_l or $opt_l > 0);
- system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
- if $forward_master;
- unless ($opt_i) {
- system('git', 'read-tree', '-m', '-u', 'SVN2GIT_HEAD', 'HEAD');
- die "read-tree failed: $?\n" if $?;
- }
-} else {
- $orig_branch = "master";
- print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0);
- system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
- unless -f "$git_dir/refs/heads/master";
- system('git', 'update-ref', 'HEAD', "$orig_branch");
- unless ($opt_i) {
- system('git checkout');
- die "checkout failed: $?\n" if $?;
- }
-}
-unlink("$git_dir/SVN2GIT_HEAD");
-close(BRANCHES);
+++ /dev/null
-git-svnimport(1)
-================
-v0.1, July 2005
-
-NAME
-----
-git-svnimport - Import a SVN repository into git
-
-
-SYNOPSIS
---------
-[verse]
-'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ]
- [ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev]
- [ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ]
- [ -s start_chg ] [ -m ] [ -r ] [ -M regex ]
- [ -I <ignorefile_name> ] [ -A <author_file> ]
- [ -R <repack_each_revs>] [ -P <path_from_trunk> ]
- <SVN_repository_URL> [ <path> ]
-
-
-DESCRIPTION
------------
-Imports a SVN repository into git. It will either create a new
-repository, or incrementally import into an existing one.
-
-SVN access is done by the SVN::Perl module.
-
-git-svnimport assumes that SVN repositories are organized into one
-"trunk" directory where the main development happens, "branches/FOO"
-directories for branches, and "/tags/FOO" directories for tags.
-Other subdirectories are ignored.
-
-git-svnimport creates a file ".git/svn2git", which is required for
-incremental SVN imports.
-
-OPTIONS
--------
--C <target-dir>::
- The GIT repository to import to. If the directory doesn't
- exist, it will be created. Default is the current directory.
-
--s <start_rev>::
- Start importing at this SVN change number. The default is 1.
-+
-When importing incrementally, you might need to edit the .git/svn2git file.
-
--i::
- Import-only: don't perform a checkout after importing. This option
- ensures the working directory and index remain untouched and will
- not create them if they do not exist.
-
--T <trunk_subdir>::
- Name the SVN trunk. Default "trunk".
-
--t <tag_subdir>::
- Name the SVN subdirectory for tags. Default "tags".
-
--b <branch_subdir>::
- Name the SVN subdirectory for branches. Default "branches".
-
--o <branch-for-HEAD>::
- The 'trunk' branch from SVN is imported to the 'origin' branch within
- the git repository. Use this option if you want to import into a
- different branch.
-
--r::
- Prepend 'rX: ' to commit messages, where X is the imported
- subversion revision.
-
--u::
- Replace underscores in tag names with periods.
-
--I <ignorefile_name>::
- Import the svn:ignore directory property to files with this
- name in each directory. (The Subversion and GIT ignore
- syntaxes are similar enough that using the Subversion patterns
- directly with "-I .gitignore" will almost always just work.)
-
--A <author_file>::
- Read a file with lines on the form
-+
-------
- username = User's Full Name <email@addr.es>
-
-------
-+
-and use "User's Full Name <email@addr.es>" as the GIT
-author and committer for Subversion commits made by
-"username". If encountering a commit made by a user not in the
-list, abort.
-+
-For convenience, this data is saved to $GIT_DIR/svn-authors
-each time the -A option is provided, and read from that same
-file each time git-svnimport is run with an existing GIT
-repository without -A.
-
--m::
- Attempt to detect merges based on the commit message. This option
- will enable default regexes that try to capture the name source
- branch name from the commit message.
-
--M <regex>::
- Attempt to detect merges based on the commit message with a custom
- regex. It can be used with -m to also see the default regexes.
- You must escape forward slashes.
-
--l <max_rev>::
- Specify a maximum revision number to pull.
-+
-Formerly, this option controlled how many revisions to pull,
-due to SVN memory leaks. (These have been worked around.)
-
--R <repack_each_revs>::
- Specify how often git repository should be repacked.
-+
-The default value is 1000. git-svnimport will do imports in chunks of 1000
-revisions, after each chunk the git repository will be repacked. To disable
-this behavior specify some large value here which is greater than the number of
-revisions to import.
-
--P <path_from_trunk>::
- Partial import of the SVN tree.
-+
-By default, the whole tree on the SVN trunk (/trunk) is imported.
-'-P my/proj' will import starting only from '/trunk/my/proj'.
-This option is useful when you want to import one project from a
-svn repo which hosts multiple projects under the same trunk.
-
--v::
- Verbosity: let 'svnimport' report what it is doing.
-
--d::
- Use direct HTTP requests if possible. The "<path>" argument is used
- only for retrieving the SVN logs; the path to the contents is
- included in the SVN log.
-
--D::
- Use direct HTTP requests if possible. The "<path>" argument is used
- for retrieving the logs, as well as for the contents.
-+
-There's no safe way to automatically find out which of these options to
-use, so you need to try both. Usually, the one that's wrong will die
-with a 40x error pretty quickly.
-
-<SVN_repository_URL>::
- The URL of the SVN module you want to import. For local
- repositories, use "file:///absolute/path".
-+
-If you're using the "-d" or "-D" option, this is the URL of the SVN
-repository itself; it usually ends in "/svn".
-
-<path>::
- The path to the module you want to check out.
-
--h::
- Print a short usage message and exit.
-
-OUTPUT
-------
-If '-v' is specified, the script reports what it is doing.
-
-Otherwise, success is indicated the Unix way, i.e. by simply exiting with
-a zero exit status.
-
-Author
-------
-Written by Matthias Urlichs <smurf@smurf.noris.de>, with help from
-various participants of the git-list <git@vger.kernel.org>.
-
-Based on a cvs2git script by the same author.
-
-Documentation
---------------
-Documentation by Matthias Urlichs <smurf@smurf.noris.de>.
-
-GIT
----
-Part of the linkgit:git[7] suite
+++ /dev/null
-#!/bin/sh
-# Copyright (c) 2005 Linus Torvalds
-
-USAGE='[-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg>] <tagname> [<head>]'
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-message_given=
-annotate=
-signed=
-force=
-message=
-username=
-list=
-verify=
-LINES=0
-while test $# != 0
-do
- case "$1" in
- -a)
- annotate=1
- shift
- ;;
- -s)
- annotate=1
- signed=1
- shift
- ;;
- -f)
- force=1
- shift
- ;;
- -n)
- case "$#,$2" in
- 1,* | *,-*)
- LINES=1 # no argument
- ;;
- *) shift
- LINES=$(expr "$1" : '\([0-9]*\)')
- [ -z "$LINES" ] && LINES=1 # 1 line is default when -n is used
- ;;
- esac
- shift
- ;;
- -l)
- list=1
- shift
- case $# in
- 0) PATTERN=
- ;;
- *)
- PATTERN="$1" # select tags by shell pattern, not re
- shift
- ;;
- esac
- git rev-parse --symbolic --tags | sort |
- while read TAG
- do
- case "$TAG" in
- *$PATTERN*) ;;
- *) continue ;;
- esac
- [ "$LINES" -le 0 ] && { echo "$TAG"; continue ;}
- OBJTYPE=$(git cat-file -t "$TAG")
- case $OBJTYPE in
- tag)
- ANNOTATION=$(git cat-file tag "$TAG" |
- sed -e '1,/^$/d' |
- sed -n -e "
- /^-----BEGIN PGP SIGNATURE-----\$/q
- 2,\$s/^/ /
- p
- ${LINES}q
- ")
- printf "%-15s %s\n" "$TAG" "$ANNOTATION"
- ;;
- *) echo "$TAG"
- ;;
- esac
- done
- ;;
- -m)
- annotate=1
- shift
- message="$1"
- if test "$#" = "0"; then
- die "error: option -m needs an argument"
- else
- message="$1"
- message_given=1
- shift
- fi
- ;;
- -F)
- annotate=1
- shift
- if test "$#" = "0"; then
- die "error: option -F needs an argument"
- else
- message="$(cat "$1")"
- message_given=1
- shift
- fi
- ;;
- -u)
- annotate=1
- signed=1
- shift
- if test "$#" = "0"; then
- die "error: option -u needs an argument"
- else
- username="$1"
- shift
- fi
- ;;
- -d)
- shift
- had_error=0
- for tag
- do
- cur=$(git show-ref --verify --hash -- "refs/tags/$tag") || {
- echo >&2 "Seriously, what tag are you talking about?"
- had_error=1
- continue
- }
- git update-ref -m 'tag: delete' -d "refs/tags/$tag" "$cur" || {
- had_error=1
- continue
- }
- echo "Deleted tag $tag."
- done
- exit $had_error
- ;;
- -v)
- shift
- tag_name="$1"
- tag=$(git show-ref --verify --hash -- "refs/tags/$tag_name") ||
- die "Seriously, what tag are you talking about?"
- git-verify-tag -v "$tag"
- exit $?
- ;;
- -*)
- usage
- ;;
- *)
- break
- ;;
- esac
-done
-
-[ -n "$list" ] && exit 0
-
-name="$1"
-[ "$name" ] || usage
-prev=0000000000000000000000000000000000000000
-if git show-ref --verify --quiet -- "refs/tags/$name"
-then
- test -n "$force" || die "tag '$name' already exists"
- prev=$(git rev-parse "refs/tags/$name")
-fi
-shift
-git check-ref-format "tags/$name" ||
- die "we do not like '$name' as a tag name."
-
-object=$(git rev-parse --verify --default HEAD "$@") || exit 1
-type=$(git cat-file -t $object) || exit 1
-tagger=$(git var GIT_COMMITTER_IDENT) || exit 1
-
-test -n "$username" ||
- username=$(git config user.signingkey) ||
- username=$(expr "z$tagger" : 'z\(.*>\)')
-
-trap 'rm -f "$GIT_DIR"/TAG_TMP* "$GIT_DIR"/TAG_FINALMSG "$GIT_DIR"/TAG_EDITMSG' 0
-
-if [ "$annotate" ]; then
- if [ -z "$message_given" ]; then
- ( echo "#"
- echo "# Write a tag message"
- echo "#" ) > "$GIT_DIR"/TAG_EDITMSG
- git_editor "$GIT_DIR"/TAG_EDITMSG || exit
- else
- printf '%s\n' "$message" >"$GIT_DIR"/TAG_EDITMSG
- fi
-
- grep -v '^#' <"$GIT_DIR"/TAG_EDITMSG |
- git stripspace >"$GIT_DIR"/TAG_FINALMSG
-
- [ -s "$GIT_DIR"/TAG_FINALMSG -o -n "$message_given" ] || {
- echo >&2 "No tag message?"
- exit 1
- }
-
- ( printf 'object %s\ntype %s\ntag %s\ntagger %s\n\n' \
- "$object" "$type" "$name" "$tagger";
- cat "$GIT_DIR"/TAG_FINALMSG ) >"$GIT_DIR"/TAG_TMP
- rm -f "$GIT_DIR"/TAG_TMP.asc "$GIT_DIR"/TAG_FINALMSG
- if [ "$signed" ]; then
- gpg -bsa -u "$username" "$GIT_DIR"/TAG_TMP &&
- cat "$GIT_DIR"/TAG_TMP.asc >>"$GIT_DIR"/TAG_TMP ||
- die "failed to sign the tag with GPG."
- fi
- object=$(git-mktag < "$GIT_DIR"/TAG_TMP)
-fi
-
-git update-ref "refs/tags/$name" "$object" "$prev"
+++ /dev/null
-#!/bin/sh
-
-USAGE='<tag>'
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-verbose=
-while test $# != 0
-do
- case "$1" in
- -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
- verbose=t ;;
- *)
- break ;;
- esac
- shift
-done
-
-if [ "$#" != "1" ]
-then
- usage
-fi
-
-type="$(git cat-file -t "$1" 2>/dev/null)" ||
- die "$1: no such object."
-
-test "$type" = tag ||
- die "$1: cannot verify a non-tag object of type $type."
-
-case "$verbose" in
-t)
- git cat-file -p "$1" |
- sed -n -e '/^-----BEGIN PGP SIGNATURE-----/q' -e p
- ;;
-esac
-
-trap 'rm -f "$GIT_DIR/.tmp-vtag"' 0
-
-git cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1
-sed -n -e '
- /^-----BEGIN PGP SIGNATURE-----$/q
- p
-' <"$GIT_DIR/.tmp-vtag" |
-gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1
-rm -f "$GIT_DIR/.tmp-vtag"
+++ /dev/null
-#!/bin/sh
-
-USAGE='[-p] [--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [-m] [git-diff-tree options] [git-rev-list options]'
-SUBDIRECTORY_OK='Yes'
-. git-sh-setup
-
-diff_tree_flags=$(git-rev-parse --sq --no-revs --flags "$@") || exit
-case "$0" in
-*whatchanged)
- count=
- test -z "$diff_tree_flags" &&
- diff_tree_flags=$(git config --get whatchanged.difftree)
- diff_tree_default_flags='-c -M --abbrev' ;;
-*show)
- count=-n1
- test -z "$diff_tree_flags" &&
- diff_tree_flags=$(git config --get show.difftree)
- diff_tree_default_flags='--cc --always' ;;
-esac
-test -z "$diff_tree_flags" &&
- diff_tree_flags="$diff_tree_default_flags"
-
-rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") &&
-diff_tree_args=$(git-rev-parse --sq --no-revs --no-flags "$@") &&
-
-eval "git-rev-list $count $rev_list_args" |
-eval "git-diff-tree --stdin --pretty -r $diff_tree_flags $diff_tree_args" |
-LESS="$LESS -S" ${PAGER:-less}
to_free = strbuf_detach(buf, NULL);
hash_object_file(src, len, "blob", &oid);
- strbuf_grow(buf, len + cnt * 43);
+ strbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + 3));
for (;;) {
/* step 1: run to the next '$' */
dollar = memchr(src, '$', len);
struct stream_filter filter;
struct strbuf left;
int state;
- char ident[45]; /* ": x40 $" */
+ char ident[GIT_MAX_HEXSZ + 5]; /* ": x40 $" */
};
static int is_foreign_ident(const char *str)
ident_free_fn,
};
-static struct stream_filter *ident_filter(const unsigned char *sha1)
+static struct stream_filter *ident_filter(const struct object_id *oid)
{
struct ident_filter *ident = xmalloc(sizeof(*ident));
xsnprintf(ident->ident, sizeof(ident->ident),
- ": %s $", sha1_to_hex(sha1));
+ ": %s $", oid_to_hex(oid));
strbuf_init(&ident->left, 0);
ident->filter.vtbl = &ident_vtbl;
ident->state = 0;
* Note that you would be crazy to set CRLF, smuge/clean or ident to a
* large binary blob you would want us not to slurp into the memory!
*/
-struct stream_filter *get_stream_filter(const char *path, const unsigned char *sha1)
+struct stream_filter *get_stream_filter(const char *path, const struct object_id *oid)
{
struct conv_attrs ca;
struct stream_filter *filter = NULL;
return NULL;
if (ca.ident)
- filter = ident_filter(sha1);
+ filter = ident_filter(oid);
if (output_eol(ca.crlf_action) == EOL_CRLF)
filter = cascade_filter(filter, lf_to_crlf_filter());
struct stream_filter; /* opaque */
-extern struct stream_filter *get_stream_filter(const char *path, const unsigned char *);
+extern struct stream_filter *get_stream_filter(const char *path, const struct object_id *);
extern void free_stream_filter(struct stream_filter *);
extern int is_null_stream_filter(struct stream_filter *);
#include "run-command.h"
#include "url.h"
#include "prompt.h"
+#include "sigchain.h"
void credential_init(struct credential *c)
{
return -1;
fp = xfdopen(helper.in, "w");
+ sigchain_push(SIGPIPE, SIG_IGN);
credential_write(c, fp);
fclose(fp);
+ sigchain_pop(SIGPIPE);
if (want_output) {
int r;
else {
enum object_type type;
if (size_only || (flags & CHECK_BINARY)) {
- type = sha1_object_info(s->oid.hash, &s->size);
+ type = oid_object_info(&s->oid, &s->size);
if (type < 0)
die("unable to read %s",
oid_to_hex(&s->oid));
return 0;
}
}
- s->data = read_sha1_file(s->oid.hash, &type, &s->size);
+ s->data = read_object_file(&s->oid, &type, &s->size);
if (!s->data)
die("unable to read %s", oid_to_hex(&s->oid));
s->should_free = 1;
static const char *diff_abbrev_oid(const struct object_id *oid, int abbrev)
{
if (startup_info->have_repository)
- return find_unique_abbrev(oid->hash, abbrev);
+ return find_unique_abbrev(oid, abbrev);
else {
char *hex = oid_to_hex(oid);
if (abbrev < 0)
*size_out = 0;
*data_out = NULL;
- data = read_sha1_file(oid->hash, &type, &sz);
+ data = read_object_file(oid, &type, &sz);
if (!data || type != OBJ_BLOB) {
free(data);
return -1;
static void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
{
enum object_type type;
- void *blob_data = read_sha1_file(ce->oid.hash, &type, size);
+ void *blob_data = read_object_file(&ce->oid, &type, size);
if (blob_data) {
if (type == OBJ_BLOB)
if (ce_mode_s_ifmt == S_IFREG) {
struct stream_filter *filter = get_stream_filter(ce->name,
- ce->oid.hash);
+ &ce->oid);
if (filter &&
!streaming_write_entry(ce, path, filter,
state, to_tempfile,
#include "refs.h"
#include "fmt-merge-msg.h"
#include "commit.h"
+#include "argv-array.h"
+#include "object-store.h"
int trust_executable_bit = 1;
int trust_ctime = 1;
return strbuf_detach(&buf, NULL);
}
-void setup_git_env(void)
+/*
+ * Wrapper of getenv() that returns a strdup value. This value is kept
+ * in argv to be freed later.
+ */
+static const char *getenv_safe(struct argv_array *argv, const char *name)
+{
+ const char *value = getenv(name);
+
+ if (!value)
+ return NULL;
+
+ argv_array_push(argv, value);
+ return argv->argv[argv->argc - 1];
+}
+
+void setup_git_env(const char *git_dir)
{
const char *shallow_file;
const char *replace_ref_base;
+ struct set_gitdir_args args = { NULL };
+ struct argv_array to_free = ARGV_ARRAY_INIT;
+
+ args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);
+ args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);
+ args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);
+ args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);
+ args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);
+ repo_set_gitdir(the_repository, git_dir, &args);
+ argv_array_clear(&to_free);
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
check_replace_refs = 0;
char *get_object_directory(void)
{
- if (!the_repository->objectdir)
+ if (!the_repository->objects->objectdir)
BUG("git environment hasn't been setup");
- return the_repository->objectdir;
+ return the_repository->objects->objectdir;
}
int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
{
if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
return error("Could not set GIT_DIR to '%s'", path);
- repo_set_gitdir(the_repository, path);
- setup_git_env();
+ setup_git_env(path);
return 0;
}
#include "builtin.h"
#include "cache.h"
+#include "repository.h"
#include "config.h"
#include "lockfile.h"
#include "object.h"
#include "dir.h"
#include "run-command.h"
#include "packfile.h"
+#include "object-store.h"
#define PACK_ID_BITS 16
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
if (!new_p)
die("core git rejected index %s", idx_name);
all_packs[pack_id] = new_p;
- install_packed_git(new_p);
+ install_packed_git(the_repository, new_p);
free(idx_name);
/* Print the boundary */
if (e->idx.offset) {
duplicate_count_by_type[type]++;
return 1;
- } else if (find_sha1_pack(oid.hash, packed_git)) {
+ } else if (find_sha1_pack(oid.hash,
+ get_packed_git(the_repository))) {
e->type = type;
e->pack_id = MAX_PACK_ID;
e->idx.offset = 1; /* just not zero! */
duplicate_count_by_type[OBJ_BLOB]++;
truncate_pack(&checkpoint);
- } else if (find_sha1_pack(oid.hash, packed_git)) {
+ } else if (find_sha1_pack(oid.hash,
+ get_packed_git(the_repository))) {
e->type = OBJ_BLOB;
e->pack_id = MAX_PACK_ID;
e->idx.offset = 1; /* just not zero! */
die("Can't load tree %s", oid_to_hex(oid));
} else {
enum object_type type;
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf || type != OBJ_TREE)
die("Can't load tree %s", oid_to_hex(oid));
}
die("corrupt mark line: %s", line);
e = find_object(&oid);
if (!e) {
- enum object_type type = sha1_object_info(oid.hash, NULL);
+ enum object_type type = oid_object_info(&oid, NULL);
if (type < 0)
die("object not found: %s", oid_to_hex(&oid));
e = insert_object(&oid);
enum object_type expected = S_ISDIR(mode) ?
OBJ_TREE: OBJ_BLOB;
enum object_type type = oe ? oe->type :
- sha1_object_info(oid.hash, NULL);
+ oid_object_info(&oid, NULL);
if (type < 0)
die("%s not found: %s",
S_ISDIR(mode) ? "Tree" : "Blob",
oidcpy(&commit_oid, &commit_oe->idx.oid);
} else if (!get_oid(p, &commit_oid)) {
unsigned long size;
- char *buf = read_object_with_reference(commit_oid.hash,
- commit_type, &size, commit_oid.hash);
+ char *buf = read_object_with_reference(&commit_oid,
+ commit_type, &size,
+ &commit_oid);
if (!buf || size < 46)
die("Not a valid commit: %s", p);
free(buf);
die("Not a blob (actually a %s): %s",
type_name(oe->type), command_buf.buf);
} else if (!is_null_oid(&oid)) {
- enum object_type type = sha1_object_info(oid.hash, NULL);
+ enum object_type type = oid_object_info(&oid, NULL);
if (type < 0)
die("Blob not found: %s", command_buf.buf);
if (type != OBJ_BLOB)
unsigned long size;
char *buf;
- buf = read_object_with_reference(b->oid.hash,
- commit_type, &size,
- b->oid.hash);
+ buf = read_object_with_reference(&b->oid, commit_type, &size,
+ &b->oid);
parse_from_commit(b, buf, size);
free(buf);
}
oidcpy(&n->oid, &oe->idx.oid);
} else if (!get_oid(from, &n->oid)) {
unsigned long size;
- char *buf = read_object_with_reference(n->oid.hash,
- commit_type, &size, n->oid.hash);
+ char *buf = read_object_with_reference(&n->oid,
+ commit_type,
+ &size, &n->oid);
if (!buf || size < 46)
die("Not a valid commit: %s", from);
free(buf);
} else if (!get_oid(from, &oid)) {
struct object_entry *oe = find_object(&oid);
if (!oe) {
- type = sha1_object_info(oid.hash, NULL);
+ type = oid_object_info(&oid, NULL);
if (type < 0)
die("Not a valid object: %s", from);
} else
char *buf;
if (!oe || oe->pack_id == MAX_PACK_ID) {
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
} else {
type = oe->type;
buf = gfi_unpack_entry(oe, &size);
unsigned long size;
char *buf = NULL;
if (!oe) {
- enum object_type type = sha1_object_info(oid->hash, NULL);
+ enum object_type type = oid_object_info(oid, NULL);
if (type < 0)
die("object not found: %s", oid_to_hex(oid));
/* cache it! */
buf = gfi_unpack_entry(oe, &size);
} else {
enum object_type unused;
- buf = read_sha1_file(oid->hash, &unused, &size);
+ buf = read_object_file(oid, &unused, &size);
}
if (!buf)
die("Can't load object %s", oid_to_hex(oid));
rc_free[i].next = &rc_free[i + 1];
rc_free[cmd_save - 1].next = NULL;
- prepare_packed_git();
start_packfile();
set_die_routine(die_nicely);
set_checkpoint_signal();
#include "cache.h"
+#include "repository.h"
#include "config.h"
#include "lockfile.h"
#include "refs.h"
mark_complete(&obj->oid);
}
+struct loose_object_iter {
+ struct oidset *loose_object_set;
+ struct ref *refs;
+};
+
+/*
+ * If the number of refs is not larger than the number of loose objects,
+ * this function stops inserting.
+ */
+static int add_loose_objects_to_set(const struct object_id *oid,
+ const char *path,
+ void *data)
+{
+ struct loose_object_iter *iter = data;
+ oidset_insert(iter->loose_object_set, oid);
+ if (iter->refs == NULL)
+ return 1;
+
+ iter->refs = iter->refs->next;
+ return 0;
+}
+
static int everything_local(struct fetch_pack_args *args,
struct ref **refs,
struct ref **sought, int nr_sought)
int retval;
int old_save_commit_buffer = save_commit_buffer;
timestamp_t cutoff = 0;
+ struct oidset loose_oid_set = OIDSET_INIT;
+ int use_oidset = 0;
+ struct loose_object_iter iter = {&loose_oid_set, *refs};
+
+ /* Enumerate all loose objects or know refs are not so many. */
+ use_oidset = !for_each_loose_object(add_loose_objects_to_set,
+ &iter, 0);
save_commit_buffer = 0;
for (ref = *refs; ref; ref = ref->next) {
struct object *o;
+ unsigned int flags = OBJECT_INFO_QUICK;
- if (!has_object_file_with_flags(&ref->old_oid,
- OBJECT_INFO_QUICK))
- continue;
+ if (use_oidset &&
+ !oidset_contains(&loose_oid_set, &ref->old_oid)) {
+ /*
+ * I know this does not exist in the loose form,
+ * so check if it exists in a non-loose form.
+ */
+ flags |= OBJECT_INFO_IGNORE_LOOSE;
+ }
+ if (!has_object_file_with_flags(&ref->old_oid, flags))
+ continue;
o = parse_object(&ref->old_oid);
if (!o)
continue;
}
}
+ oidset_clear(&loose_oid_set);
+
if (!args->no_dependents) {
if (!args->deepen) {
for_each_ref(mark_complete_oid, NULL);
prepare_shallow_info(&si, shallow);
ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
&si, pack_lockfile);
- reprepare_packed_git();
+ reprepare_packed_git(the_repository);
update_shallow(args, sought, nr_sought, &si);
clear_shallow_info(&si);
return ref_cpy;
enum object_type type;
buffer = to_free =
- read_sha1_file(tag->object.oid.hash, &type, &size);
+ read_object_file(&tag->object.oid, &type, &size);
if (!buffer)
return report(options, &tag->object,
FSCK_MSG_MISSING_TAG_OBJECT,
# The refs should be updated if their heads were rewritten
git rev-parse --no-flags --revs-only --symbolic-full-name \
- --default HEAD "$@" > "$tempdir"/raw-heads || exit
-sed -e '/^^/d' "$tempdir"/raw-heads >"$tempdir"/heads
+ --default HEAD "$@" > "$tempdir"/raw-refs || exit
+while read ref
+do
+ case "$ref" in ^?*) continue ;; esac
+
+ if git rev-parse --verify "$ref"^0 >/dev/null 2>&1
+ then
+ echo "$ref"
+ else
+ warn "WARNING: not rewriting '$ref' (not a committish)"
+ fi
+done >"$tempdir"/heads <"$tempdir"/raw-refs
test -s "$tempdir"/heads ||
die "You must specify a ref to rewrite."
die "Could not get the commits"
commits=$(wc -l <../revs | tr -d " ")
-test $commits -eq 0 && die "Found nothing to rewrite"
+test $commits -eq 0 && die_with_status 2 "Found nothing to rewrite"
# Rewrite the commits
report_progress ()
# Copyright (c) 2010 Junio C Hamano.
#
-# The whole contents of this file is run by dot-sourcing it from
-# inside a shell function. It used to be that "return"s we see
-# below were not inside any function, and expected to return
-# to the function that dot-sourced us.
-#
-# However, older (9.x) versions of FreeBSD /bin/sh misbehave on such a
-# construct and continue to run the statements that follow such a "return".
-# As a work-around, we introduce an extra layer of a function
-# here, and immediately call it after defining it.
git_rebase__am () {
case "$action" in
move_to_original_branch
}
-# ... and then we call the whole thing.
-git_rebase__am
esac
sha1=$(git rev-parse $sha1)
- if test -f "$state_dir"/current-commit
+ if test -f "$state_dir"/current-commit && test "$fast_forward" = t
then
- if test "$fast_forward" = t
- then
- while read current_commit
- do
- git rev-parse HEAD > "$rewritten"/$current_commit
- done <"$state_dir"/current-commit
- rm "$state_dir"/current-commit ||
- die "$(gettext "Cannot write current commit's replacement sha1")"
- fi
+ while read current_commit
+ do
+ git rev-parse HEAD > "$rewritten"/$current_commit
+ done <"$state_dir"/current-commit
+ rm "$state_dir"/current-commit ||
+ die "$(gettext "Cannot write current commit's replacement sha1")"
fi
echo $sha1 >> "$state_dir"/current-commit
printf '%s' "$check_level" | tr 'A-Z' 'a-z'
}
-# The whole contents of this file is run by dot-sourcing it from
-# inside a shell function. It used to be that "return"s we see
-# below were not inside any function, and expected to return
-# to the function that dot-sourced us.
+# Initiate an action. If the cannot be any
+# further action it may exec a command
+# or exit and not return.
#
-# However, older (9.x) versions of FreeBSD /bin/sh misbehave on such a
-# construct and continue to run the statements that follow such a "return".
-# As a work-around, we introduce an extra layer of a function
-# here, and immediately call it after defining it.
-git_rebase__interactive () {
-
-case "$action" in
-continue)
- if test ! -d "$rewritten"
- then
- exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
- --continue
- fi
- # do we have anything to commit?
- if git diff-index --cached --quiet HEAD --
- then
- # Nothing to commit -- skip this commit
-
- test ! -f "$GIT_DIR"/CHERRY_PICK_HEAD ||
- rm "$GIT_DIR"/CHERRY_PICK_HEAD ||
- die "$(gettext "Could not remove CHERRY_PICK_HEAD")"
- else
- if ! test -f "$author_script"
+# TODO: Consider a cleaner return model so it
+# never exits and always return 0 if process
+# is complete.
+#
+# Parameter 1 is the action to initiate.
+#
+# Returns 0 if the action was able to complete
+# and if 1 if further processing is required.
+initiate_action () {
+ case "$1" in
+ continue)
+ if test ! -d "$rewritten"
+ then
+ exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+ --continue
+ fi
+ # do we have anything to commit?
+ if git diff-index --cached --quiet HEAD --
then
- gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")}
- die "$(eval_gettext "\
+ # Nothing to commit -- skip this commit
+
+ test ! -f "$GIT_DIR"/CHERRY_PICK_HEAD ||
+ rm "$GIT_DIR"/CHERRY_PICK_HEAD ||
+ die "$(gettext "Could not remove CHERRY_PICK_HEAD")"
+ else
+ if ! test -f "$author_script"
+ then
+ gpg_sign_opt_quoted=${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")}
+ die "$(eval_gettext "\
You have staged changes in your working tree.
If these changes are meant to be
squashed into the previous commit, run:
git rebase --continue
")"
- fi
- . "$author_script" ||
- die "$(gettext "Error trying to find the author identity to amend commit")"
- if test -f "$amend"
- then
- current_head=$(git rev-parse --verify HEAD)
- test "$current_head" = $(cat "$amend") ||
- die "$(gettext "\
+ fi
+ . "$author_script" ||
+ die "$(gettext "Error trying to find the author identity to amend commit")"
+ if test -f "$amend"
+ then
+ current_head=$(git rev-parse --verify HEAD)
+ test "$current_head" = $(cat "$amend") ||
+ die "$(gettext "\
You have uncommitted changes in your working tree. Please commit them
first and then run 'git rebase --continue' again.")"
- do_with_author git commit --amend --no-verify -F "$msg" -e \
- ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
- die "$(gettext "Could not commit staged changes.")"
- else
- do_with_author git commit --no-verify -F "$msg" -e \
- ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
- die "$(gettext "Could not commit staged changes.")"
+ do_with_author git commit --amend --no-verify -F "$msg" -e \
+ ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
+ die "$(gettext "Could not commit staged changes.")"
+ else
+ do_with_author git commit --no-verify -F "$msg" -e \
+ ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
+ die "$(gettext "Could not commit staged changes.")"
+ fi
fi
- fi
- if test -r "$state_dir"/stopped-sha
+ if test -r "$state_dir"/stopped-sha
+ then
+ record_in_rewritten "$(cat "$state_dir"/stopped-sha)"
+ fi
+
+ require_clean_work_tree "rebase"
+ do_rest
+ return 0
+ ;;
+ skip)
+ git rerere clear
+
+ if test ! -d "$rewritten"
+ then
+ exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+ --continue
+ fi
+ do_rest
+ return 0
+ ;;
+ edit-todo)
+ git stripspace --strip-comments <"$todo" >"$todo".new
+ mv -f "$todo".new "$todo"
+ collapse_todo_ids
+ append_todo_help
+ gettext "
+You are editing the todo file of an ongoing interactive rebase.
+To continue rebase after editing, run:
+ git rebase --continue
+
+" | git stripspace --comment-lines >>"$todo"
+
+ git_sequence_editor "$todo" ||
+ die "$(gettext "Could not execute editor")"
+ expand_todo_ids
+
+ exit
+ ;;
+ show-current-patch)
+ exec git show REBASE_HEAD --
+ ;;
+ *)
+ return 1 # continue
+ ;;
+ esac
+}
+
+setup_reflog_action () {
+ comment_for_reflog start
+
+ if test ! -z "$switch_to"
then
- record_in_rewritten "$(cat "$state_dir"/stopped-sha)"
+ GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to"
+ output git checkout "$switch_to" -- ||
+ die "$(eval_gettext "Could not checkout \$switch_to")"
+
+ comment_for_reflog start
fi
+}
- require_clean_work_tree "rebase"
- do_rest
- return 0
- ;;
-skip)
- git rerere clear
+init_basic_state () {
+ orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")"
+ mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")"
+ rm -f "$(git rev-parse --git-path REBASE_HEAD)"
- if test ! -d "$rewritten"
+ : > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")"
+ write_basic_state
+}
+
+init_revisions_and_shortrevisions () {
+ shorthead=$(git rev-parse --short $orig_head)
+ shortonto=$(git rev-parse --short $onto)
+ if test -z "$rebase_root"
+ # this is now equivalent to ! -z "$upstream"
then
- exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
- --continue
+ shortupstream=$(git rev-parse --short $upstream)
+ revisions=$upstream...$orig_head
+ shortrevisions=$shortupstream..$shorthead
+ else
+ revisions=$onto...$orig_head
+ shortrevisions=$shorthead
fi
- do_rest
- return 0
- ;;
-edit-todo)
- git stripspace --strip-comments <"$todo" >"$todo".new
- mv -f "$todo".new "$todo"
- collapse_todo_ids
+}
+
+complete_action() {
+ test -s "$todo" || echo noop >> "$todo"
+ test -z "$autosquash" || git rebase--helper --rearrange-squash || exit
+ test -n "$cmd" && git rebase--helper --add-exec-commands "$cmd"
+
+ todocount=$(git stripspace --strip-comments <"$todo" | wc -l)
+ todocount=${todocount##* }
+
+cat >>"$todo" <<EOF
+
+$comment_char $(eval_ngettext \
+ "Rebase \$shortrevisions onto \$shortonto (\$todocount command)" \
+ "Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \
+ "$todocount")
+EOF
append_todo_help
gettext "
-You are editing the todo file of an ongoing interactive rebase.
-To continue rebase after editing, run:
- git rebase --continue
+ However, if you remove everything, the rebase will be aborted.
+
+ " | git stripspace --comment-lines >>"$todo"
+
+ if test -z "$keep_empty"
+ then
+ printf '%s\n' "$comment_char $(gettext "Note that empty commits are commented out")" >>"$todo"
+ fi
-" | git stripspace --comment-lines >>"$todo"
+ has_action "$todo" ||
+ return 2
+
+ cp "$todo" "$todo".backup
+ collapse_todo_ids
git_sequence_editor "$todo" ||
- die "$(gettext "Could not execute editor")"
+ die_abort "$(gettext "Could not execute editor")"
+
+ has_action "$todo" ||
+ return 2
+
+ git rebase--helper --check-todo-list || {
+ ret=$?
+ checkout_onto
+ exit $ret
+ }
+
expand_todo_ids
- exit
- ;;
-show-current-patch)
- exec git show REBASE_HEAD --
- ;;
-esac
+ test -d "$rewritten" || test -n "$force_rebase" ||
+ onto="$(git rebase--helper --skip-unnecessary-picks)" ||
+ die "Could not skip unnecessary pick commands"
-comment_for_reflog start
+ checkout_onto
+ if test -z "$rebase_root" && test ! -d "$rewritten"
+ then
+ require_clean_work_tree "rebase"
+ exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+ --continue
+ fi
+ do_rest
+}
-if test ! -z "$switch_to"
-then
- GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to"
- output git checkout "$switch_to" -- ||
- die "$(eval_gettext "Could not checkout \$switch_to")"
+git_rebase__interactive () {
+ initiate_action "$action"
+ ret=$?
+ if test $ret = 0; then
+ return 0
+ fi
- comment_for_reflog start
-fi
+ setup_reflog_action
+ init_basic_state
-orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")"
-mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")"
-rm -f "$(git rev-parse --git-path REBASE_HEAD)"
+ init_revisions_and_shortrevisions
+
+ git rebase--helper --make-script ${keep_empty:+--keep-empty} \
+ $revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
+ die "$(gettext "Could not generate todo list")"
+
+ complete_action
+}
+
+git_rebase__interactive__preserve_merges () {
+ initiate_action "$action"
+ ret=$?
+ if test $ret = 0; then
+ return 0
+ fi
+
+ setup_reflog_action
+ init_basic_state
-: > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")"
-write_basic_state
-if test t = "$preserve_merges"
-then
if test -z "$rebase_root"
then
mkdir "$rewritten" &&
echo $onto > "$rewritten"/root ||
die "$(gettext "Could not init rewritten commits")"
fi
- # No cherry-pick because our first pass is to determine
- # parents to rewrite and skipping dropped commits would
- # prematurely end our probe
- merges_option=
-else
- merges_option="--no-merges --cherry-pick"
-fi
-
-shorthead=$(git rev-parse --short $orig_head)
-shortonto=$(git rev-parse --short $onto)
-if test -z "$rebase_root"
- # this is now equivalent to ! -z "$upstream"
-then
- shortupstream=$(git rev-parse --short $upstream)
- revisions=$upstream...$orig_head
- shortrevisions=$shortupstream..$shorthead
-else
- revisions=$onto...$orig_head
- shortrevisions=$shorthead
-fi
-if test t != "$preserve_merges"
-then
- git rebase--helper --make-script ${keep_empty:+--keep-empty} \
- $revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
- die "$(gettext "Could not generate todo list")"
-else
+
+ init_revisions_and_shortrevisions
+
format=$(git config --get rebase.instructionFormat)
# the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to parse
- git rev-list $merges_option --format="%m%H ${format:-%s}" \
+ git rev-list --format="%m%H ${format:-%s}" \
--reverse --left-right --topo-order \
$revisions ${restrict_revision+^$restrict_revision} | \
sed -n "s/^>//p" |
while read -r sha1 rest
do
-
if test -z "$keep_empty" && is_empty_commit $sha1 && ! is_merge_commit $sha1
then
comment_out="$comment_char "
printf '%s\n' "${comment_out}pick $sha1 $rest" >>"$todo"
fi
done
-fi
-# Watch for commits that been dropped by --cherry-pick
-if test t = "$preserve_merges"
-then
+ # Watch for commits that been dropped by --cherry-pick
mkdir "$dropped"
# Save all non-cherry-picked changes
git rev-list $revisions --left-right --cherry-pick | \
rm "$rewritten"/$rev
fi
done
-fi
-
-test -s "$todo" || echo noop >> "$todo"
-test -z "$autosquash" || git rebase--helper --rearrange-squash || exit
-test -n "$cmd" && git rebase--helper --add-exec-commands "$cmd"
-
-todocount=$(git stripspace --strip-comments <"$todo" | wc -l)
-todocount=${todocount##* }
-
-cat >>"$todo" <<EOF
-
-$comment_char $(eval_ngettext \
- "Rebase \$shortrevisions onto \$shortonto (\$todocount command)" \
- "Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \
- "$todocount")
-EOF
-append_todo_help
-gettext "
-However, if you remove everything, the rebase will be aborted.
-
-" | git stripspace --comment-lines >>"$todo"
-
-if test -z "$keep_empty"
-then
- printf '%s\n' "$comment_char $(gettext "Note that empty commits are commented out")" >>"$todo"
-fi
-
-
-has_action "$todo" ||
- return 2
-
-cp "$todo" "$todo".backup
-collapse_todo_ids
-git_sequence_editor "$todo" ||
- die_abort "$(gettext "Could not execute editor")"
-
-has_action "$todo" ||
- return 2
-
-git rebase--helper --check-todo-list || {
- ret=$?
- checkout_onto
- exit $ret
-}
-
-expand_todo_ids
-
-test -d "$rewritten" || test -n "$force_rebase" ||
-onto="$(git rebase--helper --skip-unnecessary-picks)" ||
-die "Could not skip unnecessary pick commands"
-
-checkout_onto
-if test -z "$rebase_root" && test ! -d "$rewritten"
-then
- require_clean_work_tree "rebase"
- exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
- --continue
-fi
-do_rest
+ complete_action
}
-# ... and then we call the whole thing.
-git_rebase__interactive
say All done.
}
-# The whole contents of this file is run by dot-sourcing it from
-# inside a shell function. It used to be that "return"s we see
-# below were not inside any function, and expected to return
-# to the function that dot-sourced us.
-#
-# However, older (9.x) versions of FreeBSD /bin/sh misbehave on such a
-# construct and continue to run the statements that follow such a "return".
-# As a work-around, we introduce an extra layer of a function
-# here, and immediately call it after defining it.
git_rebase__merge () {
case "$action" in
finish_rb_merge
}
-# ... and then we call the whole thing.
-git_rebase__merge
autosquash=
fi
. git-rebase--$type
+ git_rebase__$type${preserve_merges:+__preserve_merges}
ret=$?
if test $ret -eq 0
then
no_changes () {
git diff-index --quiet --cached HEAD --ignore-submodules -- "$@" &&
git diff-files --quiet --ignore-submodules -- "$@" &&
- (test -z "$untracked" || test -z "$(untracked_files)")
+ (test -z "$untracked" || test -z "$(untracked_files "$@")")
}
untracked_files () {
if test -z "$patch_mode"
then
test "$untracked" = "all" && CLEAN_X_OPTION=-x || CLEAN_X_OPTION=
- if test -n "$untracked"
+ if test -n "$untracked" && test $# = 0
then
- git clean --force --quiet -d $CLEAN_X_OPTION -- "$@"
+ git clean --force --quiet -d $CLEAN_X_OPTION
fi
if test $# != 0
then
- git add -u -- "$@" |
- git checkout-index -z --force --stdin
- git diff-index -p --cached --binary HEAD -- "$@" | git apply --index -R
+ test -z "$untracked" && UPDATE_OPTION="-u" || UPDATE_OPTION=
+ test "$untracked" = "all" && FORCE_OPTION="--force" || FORCE_OPTION=
+ git add $UPDATE_OPTION $FORCE_OPTION -- "$@"
+ git diff-index -p --cached --binary HEAD -- "$@" |
+ git apply --index -R
else
git reset --hard -q
fi
#include "help.h"
#include "run-command.h"
+#define RUN_SETUP (1<<0)
+#define RUN_SETUP_GENTLY (1<<1)
+#define USE_PAGER (1<<2)
+/*
+ * require working tree to be present -- anything uses this needs
+ * RUN_SETUP for reading from the configuration file.
+ */
+#define NEED_WORK_TREE (1<<3)
+#define SUPPORT_SUPER_PREFIX (1<<4)
+#define DELAY_PAGER_CONFIG (1<<5)
+#define NO_PARSEOPT (1<<6) /* parse-options is not used */
+
+struct cmd_struct {
+ const char *cmd;
+ int (*fn)(int, const char **, const char *);
+ unsigned int option;
+};
+
const char git_usage_string[] =
N_("git [--version] [--help] [-C <path>] [-c <name>=<value>]\n"
" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
static int use_pager = -1;
-static void list_builtins(void);
+static void list_builtins(unsigned int exclude_option, char sep);
static void commit_pager_choice(void) {
switch (use_pager) {
(*argv)++;
(*argc)--;
} else if (!strcmp(cmd, "--list-builtins")) {
- list_builtins();
+ list_builtins(0, '\n');
+ exit(0);
+ } else if (!strcmp(cmd, "--list-parseopt-builtins")) {
+ list_builtins(NO_PARSEOPT, ' ');
exit(0);
} else {
fprintf(stderr, _("unknown option: %s\n"), cmd);
return ret;
}
-#define RUN_SETUP (1<<0)
-#define RUN_SETUP_GENTLY (1<<1)
-#define USE_PAGER (1<<2)
-/*
- * require working tree to be present -- anything uses this needs
- * RUN_SETUP for reading from the configuration file.
- */
-#define NEED_WORK_TREE (1<<3)
-#define SUPPORT_SUPER_PREFIX (1<<4)
-#define DELAY_PAGER_CONFIG (1<<5)
-
-struct cmd_struct {
- const char *cmd;
- int (*fn)(int, const char **, const char *);
- int option;
-};
-
static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
{
int status, help;
static struct cmd_struct commands[] = {
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
{ "am", cmd_am, RUN_SETUP | NEED_WORK_TREE },
- { "annotate", cmd_annotate, RUN_SETUP },
+ { "annotate", cmd_annotate, RUN_SETUP | NO_PARSEOPT },
{ "apply", cmd_apply, RUN_SETUP_GENTLY },
{ "archive", cmd_archive, RUN_SETUP_GENTLY },
{ "bisect--helper", cmd_bisect__helper, RUN_SETUP },
{ "blame", cmd_blame, RUN_SETUP },
{ "branch", cmd_branch, RUN_SETUP | DELAY_PAGER_CONFIG },
- { "bundle", cmd_bundle, RUN_SETUP_GENTLY },
+ { "bundle", cmd_bundle, RUN_SETUP_GENTLY | NO_PARSEOPT },
{ "cat-file", cmd_cat_file, RUN_SETUP },
{ "check-attr", cmd_check_attr, RUN_SETUP },
{ "check-ignore", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },
{ "check-mailmap", cmd_check_mailmap, RUN_SETUP },
- { "check-ref-format", cmd_check_ref_format },
+ { "check-ref-format", cmd_check_ref_format, NO_PARSEOPT },
{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
{ "checkout-index", cmd_checkout_index,
RUN_SETUP | NEED_WORK_TREE},
{ "clone", cmd_clone },
{ "column", cmd_column, RUN_SETUP_GENTLY },
{ "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
- { "commit-tree", cmd_commit_tree, RUN_SETUP },
+ { "commit-tree", cmd_commit_tree, RUN_SETUP | NO_PARSEOPT },
{ "config", cmd_config, RUN_SETUP_GENTLY | DELAY_PAGER_CONFIG },
{ "count-objects", cmd_count_objects, RUN_SETUP },
- { "credential", cmd_credential, RUN_SETUP_GENTLY },
+ { "credential", cmd_credential, RUN_SETUP_GENTLY | NO_PARSEOPT },
{ "describe", cmd_describe, RUN_SETUP },
- { "diff", cmd_diff },
- { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },
- { "diff-index", cmd_diff_index, RUN_SETUP },
- { "diff-tree", cmd_diff_tree, RUN_SETUP },
+ { "diff", cmd_diff, NO_PARSEOPT },
+ { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
+ { "diff-index", cmd_diff_index, RUN_SETUP | NO_PARSEOPT },
+ { "diff-tree", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT },
{ "difftool", cmd_difftool, RUN_SETUP | NEED_WORK_TREE },
{ "fast-export", cmd_fast_export, RUN_SETUP },
{ "fetch", cmd_fetch, RUN_SETUP },
- { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
+ { "fetch-pack", cmd_fetch_pack, RUN_SETUP | NO_PARSEOPT },
{ "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
{ "for-each-ref", cmd_for_each_ref, RUN_SETUP },
{ "format-patch", cmd_format_patch, RUN_SETUP },
{ "fsck", cmd_fsck, RUN_SETUP },
{ "fsck-objects", cmd_fsck, RUN_SETUP },
{ "gc", cmd_gc, RUN_SETUP },
- { "get-tar-commit-id", cmd_get_tar_commit_id },
+ { "get-tar-commit-id", cmd_get_tar_commit_id, NO_PARSEOPT },
{ "grep", cmd_grep, RUN_SETUP_GENTLY },
{ "hash-object", cmd_hash_object },
{ "help", cmd_help },
- { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
+ { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY | NO_PARSEOPT },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
{ "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY },
{ "ls-files", cmd_ls_files, RUN_SETUP },
{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
{ "ls-tree", cmd_ls_tree, RUN_SETUP },
- { "mailinfo", cmd_mailinfo, RUN_SETUP_GENTLY },
- { "mailsplit", cmd_mailsplit },
+ { "mailinfo", cmd_mailinfo, RUN_SETUP_GENTLY | NO_PARSEOPT },
+ { "mailsplit", cmd_mailsplit, NO_PARSEOPT },
{ "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
{ "merge-base", cmd_merge_base, RUN_SETUP },
{ "merge-file", cmd_merge_file, RUN_SETUP_GENTLY },
- { "merge-index", cmd_merge_index, RUN_SETUP },
- { "merge-ours", cmd_merge_ours, RUN_SETUP },
- { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
- { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
- { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
- { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
- { "merge-tree", cmd_merge_tree, RUN_SETUP },
- { "mktag", cmd_mktag, RUN_SETUP },
+ { "merge-index", cmd_merge_index, RUN_SETUP | NO_PARSEOPT },
+ { "merge-ours", cmd_merge_ours, RUN_SETUP | NO_PARSEOPT },
+ { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
+ { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
+ { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
+ { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
+ { "merge-tree", cmd_merge_tree, RUN_SETUP | NO_PARSEOPT },
+ { "mktag", cmd_mktag, RUN_SETUP | NO_PARSEOPT },
{ "mktree", cmd_mktree, RUN_SETUP },
{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
{ "name-rev", cmd_name_rev, RUN_SETUP },
{ "notes", cmd_notes, RUN_SETUP },
{ "pack-objects", cmd_pack_objects, RUN_SETUP },
- { "pack-redundant", cmd_pack_redundant, RUN_SETUP },
+ { "pack-redundant", cmd_pack_redundant, RUN_SETUP | NO_PARSEOPT },
{ "pack-refs", cmd_pack_refs, RUN_SETUP },
- { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY },
+ { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT },
{ "pickaxe", cmd_blame, RUN_SETUP },
{ "prune", cmd_prune, RUN_SETUP },
{ "prune-packed", cmd_prune_packed, RUN_SETUP },
{ "receive-pack", cmd_receive_pack },
{ "reflog", cmd_reflog, RUN_SETUP },
{ "remote", cmd_remote, RUN_SETUP },
- { "remote-ext", cmd_remote_ext },
- { "remote-fd", cmd_remote_fd },
+ { "remote-ext", cmd_remote_ext, NO_PARSEOPT },
+ { "remote-fd", cmd_remote_fd, NO_PARSEOPT },
{ "repack", cmd_repack, RUN_SETUP },
{ "replace", cmd_replace, RUN_SETUP },
{ "rerere", cmd_rerere, RUN_SETUP },
{ "reset", cmd_reset, RUN_SETUP },
- { "rev-list", cmd_rev_list, RUN_SETUP },
- { "rev-parse", cmd_rev_parse },
+ { "rev-list", cmd_rev_list, RUN_SETUP | NO_PARSEOPT },
+ { "rev-parse", cmd_rev_parse, NO_PARSEOPT },
{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
{ "rm", cmd_rm, RUN_SETUP },
{ "send-pack", cmd_send_pack, RUN_SETUP },
{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
{ "stripspace", cmd_stripspace },
- { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX},
+ { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX | NO_PARSEOPT },
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
{ "tag", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },
- { "unpack-file", cmd_unpack_file, RUN_SETUP },
- { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
+ { "unpack-file", cmd_unpack_file, RUN_SETUP | NO_PARSEOPT },
+ { "unpack-objects", cmd_unpack_objects, RUN_SETUP | NO_PARSEOPT },
{ "update-index", cmd_update_index, RUN_SETUP },
{ "update-ref", cmd_update_ref, RUN_SETUP },
{ "update-server-info", cmd_update_server_info, RUN_SETUP },
- { "upload-archive", cmd_upload_archive },
- { "upload-archive--writer", cmd_upload_archive_writer },
- { "var", cmd_var, RUN_SETUP_GENTLY },
+ { "upload-archive", cmd_upload_archive, NO_PARSEOPT },
+ { "upload-archive--writer", cmd_upload_archive_writer, NO_PARSEOPT },
+ { "var", cmd_var, RUN_SETUP_GENTLY | NO_PARSEOPT },
{ "verify-commit", cmd_verify_commit, RUN_SETUP },
{ "verify-pack", cmd_verify_pack },
{ "verify-tag", cmd_verify_tag, RUN_SETUP },
{ "version", cmd_version },
{ "whatchanged", cmd_whatchanged, RUN_SETUP },
- { "worktree", cmd_worktree, RUN_SETUP },
+ { "worktree", cmd_worktree, RUN_SETUP | NO_PARSEOPT },
{ "write-tree", cmd_write_tree, RUN_SETUP },
};
return !!get_builtin(s);
}
-static void list_builtins(void)
+static void list_builtins(unsigned int exclude_option, char sep)
{
int i;
- for (i = 0; i < ARRAY_SIZE(commands); i++)
- printf("%s\n", commands[i].cmd);
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ if (exclude_option &&
+ (commands[i].option & exclude_option))
+ continue;
+ printf("%s%c", commands[i].cmd, sep);
+ }
}
#ifdef STRIP_EXTENSION
enum object_type type;
grep_read_lock();
- gs->buf = read_sha1_file(gs->identifier, &type, &gs->size);
+ gs->buf = read_object_file(gs->identifier, &type, &gs->size);
grep_read_unlock();
if (!gs->buf)
#include "cache.h"
#include "config.h"
+#include "repository.h"
#include "refs.h"
#include "pkt-line.h"
#include "object.h"
#include "url.h"
#include "argv-array.h"
#include "packfile.h"
+#include "object-store.h"
static const char content_type[] = "Content-Type";
static const char content_length[] = "Content-Length";
size_t cnt = 0;
select_getanyfile(hdr);
- prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p; p = p->next) {
if (p->pack_local)
cnt++;
}
strbuf_grow(&buf, cnt * 53 + 2);
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p; p = p->next) {
if (p->pack_local)
strbuf_addf(&buf, "P %s\n", p->pack_name + objdirlen + 6);
}
#include "sigchain.h"
#include "argv-array.h"
#include "packfile.h"
+#include "object-store.h"
#ifdef EXPAT_NEEDS_XMLPARSE_H
#include <xmlparse.h>
ssize_t size;
git_zstream stream;
- unpacked = read_sha1_file(request->obj->oid.hash, &type, &len);
+ unpacked = read_object_file(&request->obj->oid, &type, &len);
hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(type), len) + 1;
/* Set it up */
#include "cache.h"
+#include "repository.h"
#include "commit.h"
#include "walker.h"
#include "http.h"
#include "list.h"
#include "transport.h"
#include "packfile.h"
+#include "object-store.h"
struct alt_base {
char *base;
struct object_request {
struct walker *walker;
- unsigned char sha1[20];
+ struct object_id oid;
struct alt_base *repo;
enum object_request_state state;
struct http_object_request *req;
struct active_request_slot *slot;
struct http_object_request *req;
- req = new_http_object_request(obj_req->repo->base, obj_req->sha1);
+ req = new_http_object_request(obj_req->repo->base, obj_req->oid.hash);
if (req == NULL) {
obj_req->state = ABORTED;
return;
return;
if (obj_req->req->rename == 0)
- walker_say(obj_req->walker, "got %s\n", sha1_to_hex(obj_req->sha1));
+ walker_say(obj_req->walker, "got %s\n", oid_to_hex(&obj_req->oid));
}
static void process_object_response(void *callback_data)
list_for_each_safe(pos, tmp, head) {
obj_req = list_entry(pos, struct object_request, node);
if (obj_req->state == WAITING) {
- if (has_sha1_file(obj_req->sha1))
+ if (has_sha1_file(obj_req->oid.hash))
obj_req->state = COMPLETE;
else {
start_object_request(walker, obj_req);
newreq = xmalloc(sizeof(*newreq));
newreq->walker = walker;
- hashcpy(newreq->sha1, sha1);
+ hashcpy(newreq->oid.hash, sha1);
newreq->repo = data->alt;
newreq->state = WAITING;
newreq->req = NULL;
list_for_each(pos, head) {
obj_req = list_entry(pos, struct object_request, node);
- if (!hashcmp(obj_req->sha1, sha1))
+ if (!hashcmp(obj_req->oid.hash, sha1))
break;
}
if (obj_req == NULL)
return error("Couldn't find request for %s in the queue", hex);
- if (has_sha1_file(obj_req->sha1)) {
+ if (has_sha1_file(obj_req->oid.hash)) {
if (obj_req->req != NULL)
abort_http_object_request(obj_req->req);
abort_object_request(obj_req);
} else if (req->zret != Z_STREAM_END) {
walker->corrupt_object_found++;
ret = error("File %s (%s) corrupt", hex, req->url);
- } else if (hashcmp(obj_req->sha1, req->real_sha1)) {
+ } else if (hashcmp(obj_req->oid.hash, req->real_sha1)) {
ret = error("File %s has bad hash", hex);
} else if (req->rename < 0) {
struct strbuf buf = STRBUF_INIT;
- sha1_file_name(&buf, req->sha1);
+ sha1_file_name(the_repository, &buf, req->sha1);
ret = error("unable to write sha1 filename %s", buf.buf);
strbuf_release(&buf);
}
#include "packfile.h"
#include "protocol.h"
#include "string-list.h"
+#include "object-store.h"
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
static int trace_curl_data = 1;
{ "tlsv1.1", CURL_SSLVERSION_TLSv1_1 },
{ "tlsv1.2", CURL_SSLVERSION_TLSv1_2 },
#endif
+#if LIBCURL_VERSION_NUM >= 0x073400
+ { "tlsv1.3", CURL_SSLVERSION_TLSv1_3 },
+#endif
};
#if LIBCURL_VERSION_NUM >= 0x070903
static const char *ssl_key;
return -1;
}
- install_packed_git(p);
+ install_packed_git(the_repository, p);
free(tmp_idx);
return 0;
}
hashcpy(freq->sha1, sha1);
freq->localfile = -1;
- sha1_file_name(&filename, sha1);
+ sha1_file_name(the_repository, &filename, sha1);
snprintf(freq->tmpfile, sizeof(freq->tmpfile),
"%s.temp", filename.buf);
unlink_or_warn(freq->tmpfile);
return -1;
}
-
- sha1_file_name(&filename, freq->sha1);
+ sha1_file_name(the_repository, &filename, freq->sha1);
freq->rename = finalize_object_file(freq->tmpfile, filename.buf);
strbuf_release(&filename);
unsigned mode;
struct object_id oid;
- if (get_tree_entry(commit->object.oid.hash, spec->path,
- oid.hash, &mode))
+ if (get_tree_entry(&commit->object.oid, spec->path, &oid, &mode))
die("There is no path %s in the commit", spec->path);
fill_filespec(spec, &oid, 1, mode);
assert(obj->type == OBJ_BLOB);
assert((obj->flags & SEEN) == 0);
- t = sha1_object_info(obj->oid.hash, &object_length);
+ t = oid_object_info(&obj->oid, &object_length);
if (t != OBJ_BLOB) { /* probably OBJ_NONE */
/*
* We DO NOT have the blob locally, so we cannot
struct commit_list *p;
for (p = commit->parents; p ; p = p->next) {
struct commit *parent = p->item;
- fprintf(file, " %s", find_unique_abbrev(parent->object.oid.hash, abbrev));
+ fprintf(file, " %s", find_unique_abbrev(&parent->object.oid, abbrev));
}
}
{
struct commit_list *p = lookup_decoration(&opt->children, &commit->object);
for ( ; p; p = p->next) {
- fprintf(opt->diffopt.file, " %s", find_unique_abbrev(p->item->object.oid.hash, abbrev));
+ fprintf(opt->diffopt.file, " %s", find_unique_abbrev(&p->item->object.oid, abbrev));
}
}
if (!opt->graph)
put_revision_mark(opt, commit);
- fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), opt->diffopt.file);
+ fputs(find_unique_abbrev(&commit->object.oid, abbrev_commit), opt->diffopt.file);
if (opt->print_parents)
show_parents(commit, abbrev_commit, opt->diffopt.file);
if (opt->children.name)
if (!opt->graph)
put_revision_mark(opt, commit);
- fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit),
+ fputs(find_unique_abbrev(&commit->object.oid,
+ abbrev_commit),
opt->diffopt.file);
if (opt->print_parents)
show_parents(commit, abbrev_commit, opt->diffopt.file);
show_children(opt, commit, abbrev_commit);
if (parent)
fprintf(opt->diffopt.file, " (from %s)",
- find_unique_abbrev(parent->object.oid.hash,
- abbrev_commit));
+ find_unique_abbrev(&parent->object.oid, abbrev_commit));
fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), opt->diffopt.file);
show_decorations(opt, commit);
if (opt->commit_format == CMIT_FMT_ONELINE) {
if (get_oid(name, &oid) < 0)
return 0;
- buf = read_sha1_file(oid.hash, &type, &size);
+ buf = read_object_file(&oid, &type, &size);
if (!buf)
return error("unable to read mailmap object at %s", name);
if (type != OBJ_BLOB)
enum object_type type;
unsigned long size;
- buffer = read_sha1_file(hash->hash, &type, &size);
+ buffer = read_object_file(hash, &type, &size);
if (!buffer)
die("unable to read tree (%s)", oid_to_hex(hash));
if (type != OBJ_TREE)
if (*subpath)
subpath++;
- buf = read_sha1_file(oid1->hash, &type, &sz);
+ buf = read_object_file(oid1, &type, &sz);
if (!buf)
die("cannot read tree %s", oid_to_hex(oid1));
init_tree_desc(&desc, buf, sz);
if (!*del_prefix)
return;
- if (get_tree_entry(hash2->hash, del_prefix, shifted->hash, &mode))
+ if (get_tree_entry(hash2, del_prefix, shifted, &mode))
die("cannot find path %s in tree %s",
del_prefix, oid_to_hex(hash2));
return;
unsigned candidate = 0;
/* Can hash2 be a tree at shift_prefix in tree hash1? */
- if (!get_tree_entry(hash1->hash, shift_prefix, sub1.hash, &mode1) &&
+ if (!get_tree_entry(hash1, shift_prefix, &sub1, &mode1) &&
S_ISDIR(mode1))
candidate |= 1;
/* Can hash1 be a tree at shift_prefix in tree hash2? */
- if (!get_tree_entry(hash2->hash, shift_prefix, sub2.hash, &mode2) &&
+ if (!get_tree_entry(hash2, shift_prefix, &sub2, &mode2) &&
S_ISDIR(mode2))
candidate |= 2;
unsigned long size;
enum object_type type;
- buf = read_sha1_file(obj->object.oid.hash, &type, &size);
+ buf = read_object_file(&obj->object.oid, &type, &size);
if (!buf)
return -1;
if (type != OBJ_BLOB) {
return NULL;
if (!our)
our = their;
- return read_sha1_file(our->object.oid.hash, &type, size);
+ return read_object_file(&our->object.oid, &type, size);
}
if (fill_mmfile_blob(&f1, our) < 0)
strbuf_addf(&o->obuf, "virtual %s\n",
merge_remote_util(commit)->name);
else {
- strbuf_add_unique_abbrev(&o->obuf, commit->object.oid.hash,
+ strbuf_add_unique_abbrev(&o->obuf, &commit->object.oid,
DEFAULT_ABBREV);
strbuf_addch(&o->obuf, ' ');
if (parse_commit(commit) != 0)
return result;
}
-static int save_files_dirs(const unsigned char *sha1,
+static int save_files_dirs(const struct object_id *oid,
struct strbuf *base, const char *path,
unsigned int mode, int stage, void *context)
{
{
struct string_list_item *item;
struct stage_data *e = xcalloc(1, sizeof(struct stage_data));
- get_tree_entry(o->object.oid.hash, path,
- e->stages[1].oid.hash, &e->stages[1].mode);
- get_tree_entry(a->object.oid.hash, path,
- e->stages[2].oid.hash, &e->stages[2].mode);
- get_tree_entry(b->object.oid.hash, path,
- e->stages[3].oid.hash, &e->stages[3].mode);
+ get_tree_entry(&o->object.oid, path,
+ &e->stages[1].oid, &e->stages[1].mode);
+ get_tree_entry(&a->object.oid, path,
+ &e->stages[2].oid, &e->stages[2].mode);
+ get_tree_entry(&b->object.oid, path,
+ &e->stages[3].oid, &e->stages[3].mode);
item = string_list_insert(entries, path);
item->util = e;
return e;
goto update_index;
}
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf)
return err(o, _("cannot read object %s '%s'"), oid_to_hex(oid), path);
if (type != OBJ_BLOB) {
void *buf;
enum object_type type;
unsigned long size;
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf)
return err(o, _("cannot read object %s"), oid_to_hex(oid));
if (type != OBJ_BLOB) {
value_oid = get_note(&c->tree, key_oid);
if (!value_oid)
return NULL;
- value = read_sha1_file(value_oid->hash, &type, &size);
+ value = read_object_file(value_oid, &type, &size);
*outsize = size;
return value;
{
enum object_type type;
unsigned long size;
- void *buf = read_sha1_file(note->hash, &type, &size);
+ void *buf = read_object_file(note, &type, &size);
if (!buf)
die("cannot read note %s for object %s",
/* read in both note blob objects */
if (!is_null_oid(new_oid))
- new_msg = read_sha1_file(new_oid->hash, &new_type, &new_len);
+ new_msg = read_object_file(new_oid, &new_type, &new_len);
if (!new_msg || !new_len || new_type != OBJ_BLOB) {
free(new_msg);
return 0;
}
if (!is_null_oid(cur_oid))
- cur_msg = read_sha1_file(cur_oid->hash, &cur_type, &cur_len);
+ cur_msg = read_object_file(cur_oid, &cur_type, &cur_len);
if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) {
free(cur_msg);
free(new_msg);
return 0;
/* read_sha1_file NUL-terminates */
- data = read_sha1_file(oid->hash, &t, &len);
+ data = read_object_file(oid, &t, &len);
if (t != OBJ_BLOB || !data || !len) {
free(data);
return t != OBJ_BLOB || !data;
return;
if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, &object_oid))
die("Cannot use notes ref %s", notes_ref);
- if (get_tree_entry(object_oid.hash, "", oid.hash, &mode))
+ if (get_tree_entry(&object_oid, "", &oid, &mode))
die("Failed to read notes tree referenced by %s (%s)",
notes_ref, oid_to_hex(&object_oid));
if (!oid)
return;
- if (!(msg = read_sha1_file(oid->hash, &type, &msglen)) || type != OBJ_BLOB) {
+ if (!(msg = read_object_file(oid, &type, &msglen)) || type != OBJ_BLOB) {
free(msg);
return;
}
--- /dev/null
+#ifndef OBJECT_STORE_H
+#define OBJECT_STORE_H
+
+struct alternate_object_database {
+ struct alternate_object_database *next;
+
+ /* see alt_scratch_buf() */
+ struct strbuf scratch;
+ size_t base_len;
+
+ /*
+ * Used to store the results of readdir(3) calls when searching
+ * for unique abbreviated hashes. This cache is never
+ * invalidated, thus it's racy and not necessarily accurate.
+ * That's fine for its purpose; don't use it for tasks requiring
+ * greater accuracy!
+ */
+ char loose_objects_subdir_seen[256];
+ struct oid_array loose_objects_cache;
+
+ /*
+ * Path to the alternative object store. If this is a relative path,
+ * it is relative to the current working directory.
+ */
+ char path[FLEX_ARRAY];
+};
+void prepare_alt_odb(struct repository *r);
+char *compute_alternate_path(const char *path, struct strbuf *err);
+typedef int alt_odb_fn(struct alternate_object_database *, void *);
+int foreach_alt_odb(alt_odb_fn, void*);
+
+/*
+ * Allocate a "struct alternate_object_database" but do _not_ actually
+ * add it to the list of alternates.
+ */
+struct alternate_object_database *alloc_alt_odb(const char *dir);
+
+/*
+ * Add the directory to the on-disk alternates file; the new entry will also
+ * take effect in the current process.
+ */
+void add_to_alternates_file(const char *dir);
+
+/*
+ * Add the directory to the in-memory list of alternates (along with any
+ * recursive alternates it points to), but do not modify the on-disk alternates
+ * file.
+ */
+void add_to_alternates_memory(const char *dir);
+
+/*
+ * Returns a scratch strbuf pre-filled with the alternate object directory,
+ * including a trailing slash, which can be used to access paths in the
+ * alternate. Always use this over direct access to alt->scratch, as it
+ * cleans up any previous use of the scratch buffer.
+ */
+struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
+
+struct packed_git {
+ struct packed_git *next;
+ struct list_head mru;
+ struct pack_window *windows;
+ off_t pack_size;
+ const void *index_data;
+ size_t index_size;
+ uint32_t num_objects;
+ uint32_t num_bad_objects;
+ unsigned char *bad_object_sha1;
+ int index_version;
+ time_t mtime;
+ int pack_fd;
+ unsigned pack_local:1,
+ pack_keep:1,
+ freshened:1,
+ do_not_close:1,
+ pack_promisor:1;
+ unsigned char sha1[20];
+ struct revindex_entry *revindex;
+ /* something like ".git/objects/pack/xxxxx.pack" */
+ char pack_name[FLEX_ARRAY]; /* more */
+};
+
+struct raw_object_store {
+ /*
+ * Path to the repository's object store.
+ * Cannot be NULL after initialization.
+ */
+ char *objectdir;
+
+ /* Path to extra alternate object database if not NULL */
+ char *alternate_db;
+
+ struct alternate_object_database *alt_odb_list;
+ struct alternate_object_database **alt_odb_tail;
+
+ /*
+ * private data
+ *
+ * should only be accessed directly by packfile.c
+ */
+
+ struct packed_git *packed_git;
+ /* A most-recently-used ordered version of the packed_git list. */
+ struct list_head packed_git_mru;
+
+ /*
+ * A fast, rough count of the number of objects in the repository.
+ * These two fields are not meant for direct access. Use
+ * approximate_object_count() instead.
+ */
+ unsigned long approximate_object_count;
+ unsigned approximate_object_count_valid : 1;
+
+ /*
+ * Whether packed_git has already been populated with this repository's
+ * packs.
+ */
+ unsigned packed_git_initialized : 1;
+};
+
+struct raw_object_store *raw_object_store_new(void);
+void raw_object_store_clear(struct raw_object_store *o);
+
+/*
+ * Put in `buf` the name of the file in the local object database that
+ * would be used to store a loose object with the specified sha1.
+ */
+void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned char *sha1);
+
+void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned long *size);
+
+#endif /* OBJECT_STORE_H */
#include "tree.h"
#include "commit.h"
#include "tag.h"
+#include "object-store.h"
+#include "packfile.h"
static struct object **obj_hash;
static int nr_objs, obj_hash_size;
unsigned long size;
enum object_type type;
int eaten;
- const unsigned char *repl = lookup_replace_object(oid->hash);
+ const struct object_id *repl = lookup_replace_object(oid);
void *buffer;
struct object *obj;
if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) ||
(!obj && has_object_file(oid) &&
- sha1_object_info(oid->hash, NULL) == OBJ_BLOB)) {
- if (check_sha1_signature(repl, NULL, 0, NULL) < 0) {
+ oid_object_info(oid, NULL) == OBJ_BLOB)) {
+ if (check_object_signature(repl, NULL, 0, NULL) < 0) {
error("sha1 mismatch %s", oid_to_hex(oid));
return NULL;
}
return lookup_object(oid->hash);
}
- buffer = read_sha1_file(oid->hash, &type, &size);
+ buffer = read_object_file(oid, &type, &size);
if (buffer) {
- if (check_sha1_signature(repl, buffer, size, type_name(type)) < 0) {
+ if (check_object_signature(repl, buffer, size, type_name(type)) < 0) {
free(buffer);
- error("sha1 mismatch %s", sha1_to_hex(repl));
+ error("sha1 mismatch %s", oid_to_hex(repl));
return NULL;
}
obj->flags &= ~flags;
}
}
+
+struct raw_object_store *raw_object_store_new(void)
+{
+ struct raw_object_store *o = xmalloc(sizeof(*o));
+
+ memset(o, 0, sizeof(*o));
+ INIT_LIST_HEAD(&o->packed_git_mru);
+ return o;
+}
+
+static void free_alt_odb(struct alternate_object_database *alt)
+{
+ strbuf_release(&alt->scratch);
+ oid_array_clear(&alt->loose_objects_cache);
+ free(alt);
+}
+
+static void free_alt_odbs(struct raw_object_store *o)
+{
+ while (o->alt_odb_list) {
+ struct alternate_object_database *next;
+
+ next = o->alt_odb_list->next;
+ free_alt_odb(o->alt_odb_list);
+ o->alt_odb_list = next;
+ }
+}
+
+void raw_object_store_clear(struct raw_object_store *o)
+{
+ FREE_AND_NULL(o->objectdir);
+ FREE_AND_NULL(o->alternate_db);
+
+ free_alt_odbs(o);
+ o->alt_odb_tail = NULL;
+
+ INIT_LIST_HEAD(&o->packed_git_mru);
+ close_all_packs(o);
+ o->packed_git = NULL;
+}
break;
default:
- real_type = sha1_object_info(entry->idx.oid.hash,
- NULL);
+ real_type = oid_object_info(&entry->idx.oid, NULL);
break;
}
#include "pack-revindex.h"
#include "pack-objects.h"
#include "packfile.h"
+#include "repository.h"
+#include "object-store.h"
/*
* An entry on the bitmap index, representing the bitmap for a given
assert(!bitmap_git.map && !bitmap_git.loaded);
- prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p; p = p->next) {
if (open_pack_bitmap_1(p) == 0)
ret = 0;
}
#include "pack-revindex.h"
#include "progress.h"
#include "packfile.h"
+#include "object-store.h"
struct idx_entry {
off_t offset;
if (type == OBJ_BLOB && big_file_threshold <= size) {
/*
- * Let check_sha1_signature() check it with
+ * Let check_object_signature() check it with
* the streaming interface; no point slurping
* the data in-core only to discard.
*/
err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
oid_to_hex(entries[i].oid.oid), p->pack_name,
(uintmax_t)entries[i].offset);
- else if (check_sha1_signature(entries[i].oid.hash, data, size, type_name(type)))
+ else if (check_object_signature(entries[i].oid.oid, data, size, type_name(type)))
err = error("packed %s from %s is corrupt",
oid_to_hex(entries[i].oid.oid), p->pack_name);
else if (fn) {
#include "cache.h"
#include "pack-revindex.h"
+#include "object-store.h"
/*
* Pack index for existing packs give us easy access to the offsets into
#include "cache.h"
#include "list.h"
#include "pack.h"
+#include "repository.h"
#include "dir.h"
#include "mergesort.h"
#include "packfile.h"
#include "tag.h"
#include "tree-walk.h"
#include "tree.h"
+#include "object-store.h"
char *odb_pack_name(struct strbuf *buf,
const unsigned char *sha1,
static unsigned int pack_max_fds;
static size_t peak_pack_mapped;
static size_t pack_mapped;
-struct packed_git *packed_git;
-LIST_HEAD(packed_git_mru);
#define SZ_FMT PRIuMAX
static inline uintmax_t sz_fmt(size_t s) { return s; }
if (current)
scan_windows(current, &lru_p, &lru_w, &lru_l);
- for (p = packed_git; p; p = p->next)
+ for (p = the_repository->objects->packed_git; p; p = p->next)
scan_windows(p, &lru_p, &lru_w, &lru_l);
if (lru_p) {
munmap(lru_w->base, lru_w->len);
close_pack_index(p);
}
-void close_all_packs(void)
+void close_all_packs(struct raw_object_store *o)
{
struct packed_git *p;
- for (p = packed_git; p; p = p->next)
+ for (p = o->packed_git; p; p = p->next)
if (p->do_not_close)
die("BUG: want to close pack marked 'do-not-close'");
else
struct pack_window *mru_w = NULL;
int accept_windows_inuse = 1;
- for (p = packed_git; p; p = p->next) {
+ for (p = the_repository->objects->packed_git; p; p = p->next) {
if (p->pack_fd == -1)
continue;
find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
return p;
}
-void install_packed_git(struct packed_git *pack)
+void install_packed_git(struct repository *r, struct packed_git *pack)
{
if (pack->pack_fd != -1)
pack_open_fds++;
- pack->next = packed_git;
- packed_git = pack;
+ pack->next = r->objects->packed_git;
+ r->objects->packed_git = pack;
}
void (*report_garbage)(unsigned seen_bits, const char *path);
report_helper(list, seen_bits, first, list->nr);
}
-static void prepare_packed_git_one(char *objdir, int local)
+static void prepare_packed_git_one(struct repository *r, char *objdir, int local)
{
struct strbuf path = STRBUF_INIT;
size_t dirnamelen;
base_len = path.len;
if (strip_suffix_mem(path.buf, &base_len, ".idx")) {
/* Don't reopen a pack we already have. */
- for (p = packed_git; p; p = p->next) {
+ for (p = r->objects->packed_git; p;
+ p = p->next) {
size_t len;
if (strip_suffix(p->pack_name, ".pack", &len) &&
len == base_len &&
* corresponding .pack file that we can map.
*/
(p = add_packed_git(path.buf, path.len, local)) != NULL)
- install_packed_git(p);
+ install_packed_git(r, p);
}
if (!report_garbage)
strbuf_release(&path);
}
-static int approximate_object_count_valid;
-
+static void prepare_packed_git(struct repository *r);
/*
* Give a fast, rough count of the number of objects in the repository. This
* ignores loose objects completely. If you have a lot of them, then either
*/
unsigned long approximate_object_count(void)
{
- static unsigned long count;
- if (!approximate_object_count_valid) {
+ if (!the_repository->objects->approximate_object_count_valid) {
+ unsigned long count;
struct packed_git *p;
- prepare_packed_git();
+ prepare_packed_git(the_repository);
count = 0;
- for (p = packed_git; p; p = p->next) {
+ for (p = the_repository->objects->packed_git; p; p = p->next) {
if (open_pack_index(p))
continue;
count += p->num_objects;
}
+ the_repository->objects->approximate_object_count = count;
}
- return count;
+ return the_repository->objects->approximate_object_count;
}
static void *get_next_packed_git(const void *p)
return -1;
}
-static void rearrange_packed_git(void)
+static void rearrange_packed_git(struct repository *r)
{
- packed_git = llist_mergesort(packed_git, get_next_packed_git,
- set_next_packed_git, sort_pack);
+ r->objects->packed_git = llist_mergesort(
+ r->objects->packed_git, get_next_packed_git,
+ set_next_packed_git, sort_pack);
}
-static void prepare_packed_git_mru(void)
+static void prepare_packed_git_mru(struct repository *r)
{
struct packed_git *p;
- INIT_LIST_HEAD(&packed_git_mru);
+ INIT_LIST_HEAD(&r->objects->packed_git_mru);
- for (p = packed_git; p; p = p->next)
- list_add_tail(&p->mru, &packed_git_mru);
+ for (p = r->objects->packed_git; p; p = p->next)
+ list_add_tail(&p->mru, &r->objects->packed_git_mru);
}
-static int prepare_packed_git_run_once = 0;
-void prepare_packed_git(void)
+static void prepare_packed_git(struct repository *r)
{
struct alternate_object_database *alt;
- if (prepare_packed_git_run_once)
+ if (r->objects->packed_git_initialized)
return;
- prepare_packed_git_one(get_object_directory(), 1);
- prepare_alt_odb();
- for (alt = alt_odb_list; alt; alt = alt->next)
- prepare_packed_git_one(alt->path, 0);
- rearrange_packed_git();
- prepare_packed_git_mru();
- prepare_packed_git_run_once = 1;
+ prepare_packed_git_one(r, r->objects->objectdir, 1);
+ prepare_alt_odb(r);
+ for (alt = r->objects->alt_odb_list; alt; alt = alt->next)
+ prepare_packed_git_one(r, alt->path, 0);
+ rearrange_packed_git(r);
+ prepare_packed_git_mru(r);
+ r->objects->packed_git_initialized = 1;
+}
+
+void reprepare_packed_git(struct repository *r)
+{
+ r->objects->approximate_object_count_valid = 0;
+ r->objects->packed_git_initialized = 0;
+ prepare_packed_git(r);
+}
+
+struct packed_git *get_packed_git(struct repository *r)
+{
+ prepare_packed_git(r);
+ return r->objects->packed_git;
}
-void reprepare_packed_git(void)
+struct list_head *get_packed_git_mru(struct repository *r)
{
- approximate_object_count_valid = 0;
- prepare_packed_git_run_once = 0;
- prepare_packed_git();
+ prepare_packed_git(r);
+ return &r->objects->packed_git_mru;
}
unsigned long unpack_object_header_buffer(const unsigned char *buf,
struct packed_git *p;
unsigned i;
- for (p = packed_git; p; p = p->next)
+ for (p = the_repository->objects->packed_git; p; p = p->next)
for (i = 0; i < p->num_bad_objects; i++)
if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
return p;
{
int type;
struct revindex_entry *revidx;
- const unsigned char *sha1;
+ struct object_id oid;
revidx = find_pack_revindex(p, obj_offset);
if (!revidx)
return OBJ_BAD;
- sha1 = nth_packed_object_sha1(p, revidx->nr);
- mark_bad_packed_object(p, sha1);
- type = sha1_object_info(sha1, NULL);
+ nth_packed_object_oid(&oid, p, revidx->nr);
+ mark_bad_packed_object(p, oid.hash);
+ type = oid_object_info(&oid, NULL);
if (type <= OBJ_NONE)
return OBJ_BAD;
return type;
unsigned long size;
};
-static void *read_object(const unsigned char *sha1, enum object_type *type,
+static void *read_object(const struct object_id *oid, enum object_type *type,
unsigned long *size)
{
struct object_info oi = OBJECT_INFO_INIT;
oi.sizep = size;
oi.contentp = &content;
- if (sha1_object_info_extended(sha1, &oi, 0) < 0)
+ if (oid_object_info_extended(oid, &oi, 0) < 0)
return NULL;
return content;
}
struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
off_t len = revidx[1].offset - obj_offset;
if (check_pack_crc(p, &w_curs, obj_offset, len, revidx->nr)) {
- const unsigned char *sha1 =
- nth_packed_object_sha1(p, revidx->nr);
+ struct object_id oid;
+ nth_packed_object_oid(&oid, p, revidx->nr);
error("bad packed object CRC for %s",
- sha1_to_hex(sha1));
- mark_bad_packed_object(p, sha1);
+ oid_to_hex(&oid));
+ mark_bad_packed_object(p, oid.hash);
data = NULL;
goto out;
}
* of a corrupted pack, and is better than failing outright.
*/
struct revindex_entry *revidx;
- const unsigned char *base_sha1;
+ struct object_id base_oid;
revidx = find_pack_revindex(p, obj_offset);
if (revidx) {
- base_sha1 = nth_packed_object_sha1(p, revidx->nr);
+ nth_packed_object_oid(&base_oid, p, revidx->nr);
error("failed to read delta base object %s"
" at offset %"PRIuMAX" from %s",
- sha1_to_hex(base_sha1), (uintmax_t)obj_offset,
+ oid_to_hex(&base_oid), (uintmax_t)obj_offset,
p->pack_name);
- mark_bad_packed_object(p, base_sha1);
- base = read_object(base_sha1, &type, &base_size);
+ mark_bad_packed_object(p, base_oid.hash);
+ base = read_object(&base_oid, &type, &base_size);
external_base = base;
}
}
return data;
}
+int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32_t *result)
+{
+ const unsigned char *index_fanout = p->index_data;
+ const unsigned char *index_lookup;
+ int index_lookup_width;
+
+ if (!index_fanout)
+ BUG("bsearch_pack called without a valid pack-index");
+
+ index_lookup = index_fanout + 4 * 256;
+ if (p->index_version == 1) {
+ index_lookup_width = 24;
+ index_lookup += 4;
+ } else {
+ index_lookup_width = 20;
+ index_fanout += 8;
+ index_lookup += 8;
+ }
+
+ return bsearch_hash(oid->hash, (const uint32_t*)index_fanout,
+ index_lookup, index_lookup_width, result);
+}
+
const unsigned char *nth_packed_object_sha1(struct packed_git *p,
uint32_t n)
{
off_t find_pack_entry_one(const unsigned char *sha1,
struct packed_git *p)
{
- const uint32_t *level1_ofs = p->index_data;
const unsigned char *index = p->index_data;
- unsigned stride;
+ struct object_id oid;
uint32_t result;
if (!index) {
if (open_pack_index(p))
return 0;
- level1_ofs = p->index_data;
- index = p->index_data;
- }
- if (p->index_version > 1) {
- level1_ofs += 2;
- index += 8;
- }
- index += 4 * 256;
- if (p->index_version > 1) {
- stride = 20;
- } else {
- stride = 24;
- index += 4;
}
- if (bsearch_hash(sha1, level1_ofs, index, stride, &result))
+ hashcpy(oid.hash, sha1);
+ if (bsearch_pack(&oid, p, &result))
return nth_packed_object_offset(p, result);
return 0;
}
return 1;
}
-/*
- * Iff a pack file contains the object named by sha1, return true and
- * store its location to e.
- */
-int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
+int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack_entry *e)
{
struct list_head *pos;
- prepare_packed_git();
- if (!packed_git)
+ prepare_packed_git(r);
+ if (!r->objects->packed_git)
return 0;
- list_for_each(pos, &packed_git_mru) {
+ list_for_each(pos, &r->objects->packed_git_mru) {
struct packed_git *p = list_entry(pos, struct packed_git, mru);
if (fill_pack_entry(sha1, e, p)) {
- list_move(&p->mru, &packed_git_mru);
+ list_move(&p->mru, &r->objects->packed_git_mru);
return 1;
}
}
int has_sha1_pack(const unsigned char *sha1)
{
struct pack_entry e;
- return find_pack_entry(sha1, &e);
+ return find_pack_entry(the_repository, sha1, &e);
}
int has_pack_index(const unsigned char *sha1)
int r = 0;
int pack_errors = 0;
- prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
+ prepare_packed_git(the_repository);
+ for (p = the_repository->objects->packed_git; p; p = p->next) {
if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
continue;
if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) &&
/*
* If this is a tree, commit, or tag, the objects it refers
- * to are also promisor objects. (Blobs refer to no objects.)
+ * to are also promisor objects. (Blobs refer to no objects->)
*/
if (obj->type == OBJ_TREE) {
struct tree *tree = (struct tree *)obj;
#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);
-extern void install_packed_git(struct packed_git *pack);
+extern void reprepare_packed_git(struct repository *r);
+extern void install_packed_git(struct repository *r, struct packed_git *pack);
+
+struct packed_git *get_packed_git(struct repository *r);
+struct list_head *get_packed_git_mru(struct repository *r);
/*
* Give a rough count of objects in the repository. This sacrifices accuracy
extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
extern void close_pack_windows(struct packed_git *);
-extern void close_all_packs(void);
+extern void close_all_packs(struct raw_object_store *o);
extern void unuse_pack(struct pack_window **);
extern void clear_delta_base_cache(void);
extern struct packed_git *add_packed_git(const char *path, size_t path_len, int local);
*/
extern void check_pack_index_ptr(const struct packed_git *p, const void *ptr);
+/*
+ * Perform binary search on a pack-index for a given oid. Packfile is expected to
+ * have a valid pack-index.
+ *
+ * See 'bsearch_hash' for more information.
+ */
+int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32_t *result);
+
/*
* Return the SHA-1 of the nth object within the specified packfile.
* Open the index if it is not already open. The return value points
extern void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1);
extern const struct packed_git *has_packed_and_bad(const unsigned char *sha1);
-extern int find_pack_entry(const unsigned char *sha1, struct pack_entry *e);
+/*
+ * Iff a pack file in the given repository contains the object named by sha1,
+ * return true and store its location to e.
+ */
+extern int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack_entry *e);
extern int has_sha1_pack(const unsigned char *sha1);
return get_value(p, options, all_opts, flags ^ opt_flags);
}
- if (ambiguous_option)
- return error("Ambiguous option: %s "
+ if (ambiguous_option) {
+ error("Ambiguous option: %s "
"(could be --%s%s or --%s%s)",
arg,
(ambiguous_flags & OPT_UNSET) ? "no-" : "",
ambiguous_option->long_name,
(abbrev_flags & OPT_UNSET) ? "no-" : "",
abbrev_option->long_name);
+ return -3;
+ }
if (abbrev_option)
return get_value(p, abbrev_option, all_opts, abbrev_flags);
return -2;
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;
ctx->opt = arg + 1;
switch (parse_short_opt(ctx, options)) {
case -1:
- goto show_usage_error;
+ return PARSE_OPT_ERROR;
case -2:
if (ctx->opt)
check_typos(arg + 1, options);
while (ctx->opt) {
switch (parse_short_opt(ctx, options)) {
case -1:
- goto show_usage_error;
+ return PARSE_OPT_ERROR;
case -2:
if (internal_help && *ctx->opt == 'h')
goto show_usage;
goto show_usage;
switch (parse_long_opt(ctx, arg + 2, options)) {
case -1:
- goto show_usage_error;
+ return PARSE_OPT_ERROR;
case -2:
goto unknown;
+ case -3:
+ goto show_usage;
}
continue;
unknown:
}
return PARSE_OPT_DONE;
- show_usage_error:
- err = 1;
show_usage:
- return usage_with_options_internal(ctx, usagestr, options, 0, err);
+ return usage_with_options_internal(ctx, usagestr, options, 0, 0);
}
int parse_options_end(struct parse_opt_ctx_t *ctx)
parse_options_start(&ctx, argc, argv, prefix, options, flags);
switch (parse_options_step(&ctx, options, usagestr)) {
case PARSE_OPT_HELP:
+ case PARSE_OPT_ERROR:
exit(129);
case PARSE_OPT_NON_OPTION:
case PARSE_OPT_DONE:
PARSE_OPT_HELP = -1,
PARSE_OPT_DONE,
PARSE_OPT_NON_OPTION,
+ PARSE_OPT_ERROR,
PARSE_OPT_UNKNOWN
};
#include "submodule-config.h"
#include "path.h"
#include "packfile.h"
+#include "object-store.h"
static int get_st_mode_bits(const char *path, int *mode)
{
strbuf_splice(buf, 0, buf->len,
repo->index_file, strlen(repo->index_file));
else if (dir_prefix(base, "objects"))
- replace_dir(buf, git_dir_len + 7, repo->objectdir);
+ replace_dir(buf, git_dir_len + 7, repo->objects->objectdir);
else if (git_hooks_path && dir_prefix(base, "hooks"))
replace_dir(buf, git_dir_len + 5, git_hooks_path);
else if (repo->different_commondir)
struct object_id *oidp = &parent->item->object.oid;
strbuf_addch(sb, ' ');
if (pp->abbrev)
- strbuf_add_unique_abbrev(sb, oidp->hash, pp->abbrev);
+ strbuf_add_unique_abbrev(sb, oidp, pp->abbrev);
else
strbuf_addstr(sb, oid_to_hex(oidp));
parent = parent->next;
return 1;
case 'h': /* abbreviated commit hash */
strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
- strbuf_add_unique_abbrev(sb, commit->object.oid.hash,
+ strbuf_add_unique_abbrev(sb, &commit->object.oid,
c->pretty_ctx->abbrev);
strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
return 1;
strbuf_addstr(sb, oid_to_hex(&commit->tree->object.oid));
return 1;
case 't': /* abbreviated tree hash */
- strbuf_add_unique_abbrev(sb, commit->tree->object.oid.hash,
+ strbuf_add_unique_abbrev(sb, &commit->tree->object.oid,
c->pretty_ctx->abbrev);
return 1;
case 'P': /* parent hashes */
for (p = commit->parents; p; p = p->next) {
if (p != commit->parents)
strbuf_addch(sb, ' ');
- strbuf_add_unique_abbrev(sb, p->item->object.oid.hash,
+ strbuf_add_unique_abbrev(sb, &p->item->object.oid,
c->pretty_ctx->abbrev);
}
return 1;
#include "list-objects.h"
#include "packfile.h"
#include "worktree.h"
+#include "object-store.h"
struct connectivity_progress {
struct progress *progress;
* later processing, and the revision machinery expects
* commits and tags to have been parsed.
*/
- type = sha1_object_info(oid->hash, NULL);
+ type = oid_object_info(oid, NULL);
if (type < 0)
die("unable to get object info for %s", oid_to_hex(oid));
if (strbuf_readlink(&sb, ce->name, expected_size))
return -1;
- buffer = read_sha1_file(ce->oid.hash, &type, &size);
+ buffer = read_object_file(&ce->oid, &type, &size);
if (buffer) {
if (size == sb.len)
match = memcmp(buffer, sb.buf, size);
}
if (pos < 0)
return NULL;
- data = read_sha1_file(istate->cache[pos]->oid.hash, &type, &sz);
+ data = read_object_file(&istate->cache[pos]->oid, &type, &sz);
if (!data || type != OBJ_BLOB) {
free(data);
return NULL;
static void *get_obj(const struct object_id *oid, struct object **obj, unsigned long *sz, int *eaten)
{
enum object_type type;
- void *buf = read_sha1_file(oid->hash, &type, sz);
+ void *buf = read_object_file(oid, &type, sz);
if (buf)
*obj = parse_object_buffer(oid, type, *sz, buf, eaten);
return buf;
}
-static int grab_objectname(const char *name, const unsigned char *sha1,
+static int grab_objectname(const char *name, const struct object_id *oid,
struct atom_value *v, struct used_atom *atom)
{
if (starts_with(name, "objectname")) {
if (atom->u.objectname.option == O_SHORT) {
- v->s = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
+ v->s = xstrdup(find_unique_abbrev(oid, DEFAULT_ABBREV));
return 1;
} else if (atom->u.objectname.option == O_FULL) {
- v->s = xstrdup(sha1_to_hex(sha1));
+ v->s = xstrdup(oid_to_hex(oid));
return 1;
} else if (atom->u.objectname.option == O_LENGTH) {
- v->s = xstrdup(find_unique_abbrev(sha1, atom->u.objectname.length));
+ v->s = xstrdup(find_unique_abbrev(oid, atom->u.objectname.length));
return 1;
} else
die("BUG: unknown %%(objectname) option");
v->s = xstrfmt("%lu", sz);
}
else if (deref)
- grab_objectname(name, obj->oid.hash, v, &used_atom[i]);
+ grab_objectname(name, &obj->oid, v, &used_atom[i]);
}
}
v->s = xstrdup(buf + 1);
}
continue;
- } else if (!deref && grab_objectname(name, ref->objectname.hash, v, atom)) {
+ } else if (!deref && grab_objectname(name, &ref->objectname, v, atom)) {
continue;
} else if (!strcmp(name, "HEAD")) {
if (atom->u.head && !strcmp(ref->refname, atom->u.head))
struct object *o = lookup_unknown_object(name->hash);
if (o->type == OBJ_NONE) {
- int type = sha1_object_info(name->hash, NULL);
+ int type = oid_object_info(name, NULL);
if (type < 0 || !object_as_type(o, type, 0))
return PEEL_INVALID;
}
init_notes(NULL, notes_ref, NULL, 0);
if (!(note_oid = get_note(NULL, oid)))
return NULL; /* note tree not found */
- if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)))
+ if (!(msg = read_object_file(note_oid, &type, &msglen)))
error("Empty notes tree. %s", notes_ref);
else if (!msglen || type != OBJ_BLOB) {
error("Note contains unusable content. "
enum object_type type;
struct rev_note note;
- if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)) ||
+ if (!(msg = read_object_file(note_oid, &type, &msglen)) ||
!msglen || type != OBJ_BLOB) {
free(msg);
return 1;
continue; /* not a tag */
if (string_list_has_string(&dst_tag, ref->name))
continue; /* they already have it */
- if (sha1_object_info(ref->new_oid.hash, NULL) != OBJ_TAG)
+ if (oid_object_info(&ref->new_oid, NULL) != OBJ_TAG)
continue; /* be conservative */
item = string_list_append(&src_tag, ref->name);
item->util = ref;
* sha1.
*/
static struct replace_object {
- unsigned char original[20];
- unsigned char replacement[20];
+ struct object_id original;
+ struct object_id replacement;
} **replace_object;
static int replace_object_alloc, replace_object_nr;
static const unsigned char *replace_sha1_access(size_t index, void *table)
{
struct replace_object **replace = table;
- return replace[index]->original;
+ return replace[index]->original.hash;
}
static int replace_object_pos(const unsigned char *sha1)
static int register_replace_object(struct replace_object *replace,
int ignore_dups)
{
- int pos = replace_object_pos(replace->original);
+ int pos = replace_object_pos(replace->original.hash);
if (0 <= pos) {
if (ignore_dups)
const char *hash = slash ? slash + 1 : refname;
struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
- if (strlen(hash) != 40 || get_sha1_hex(hash, repl_obj->original)) {
+ if (get_oid_hex(hash, &repl_obj->original)) {
free(repl_obj);
warning("bad replace ref name: %s", refname);
return 0;
}
/* Copy sha1 from the read ref */
- hashcpy(repl_obj->replacement, oid->hash);
+ oidcpy(&repl_obj->replacement, oid);
/* Register new object */
if (register_replace_object(repl_obj, 1))
#define MAXREPLACEDEPTH 5
/*
- * If a replacement for object sha1 has been set up, return the
+ * If a replacement for object oid has been set up, return the
* replacement object's name (replaced recursively, if necessary).
- * The return value is either sha1 or a pointer to a
+ * The return value is either oid or a pointer to a
* permanently-allocated value. This function always respects replace
* references, regardless of the value of check_replace_refs.
*/
-const unsigned char *do_lookup_replace_object(const unsigned char *sha1)
+const struct object_id *do_lookup_replace_object(const struct object_id *oid)
{
int pos, depth = MAXREPLACEDEPTH;
- const unsigned char *cur = sha1;
+ const struct object_id *cur = oid;
prepare_replace_object();
do {
if (--depth < 0)
die("replace depth too high for object %s",
- sha1_to_hex(sha1));
+ oid_to_hex(oid));
- pos = replace_object_pos(cur);
+ pos = replace_object_pos(cur->hash);
if (0 <= pos)
- cur = replace_object[pos]->replacement;
+ cur = &replace_object[pos]->replacement;
} while (0 <= pos);
return cur;
#include "cache.h"
#include "repository.h"
+#include "object-store.h"
#include "config.h"
#include "submodule-config.h"
/* The main repository */
-static struct repository the_repo = {
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, &hash_algos[GIT_HASH_SHA1], 0, 0
-};
-struct repository *the_repository = &the_repo;
+static struct repository the_repo;
+struct repository *the_repository;
-static char *git_path_from_env(const char *envvar, const char *git_dir,
- const char *path, int fromenv)
+void initialize_the_repository(void)
{
- if (fromenv) {
- const char *value = getenv(envvar);
- if (value)
- return xstrdup(value);
- }
+ the_repository = &the_repo;
- return xstrfmt("%s/%s", git_dir, path);
+ the_repo.index = &the_index;
+ the_repo.objects = raw_object_store_new();
+ repo_set_hash_algo(&the_repo, GIT_HASH_SHA1);
}
-static int find_common_dir(struct strbuf *sb, const char *gitdir, int fromenv)
+static void expand_base_dir(char **out, const char *in,
+ const char *base_dir, const char *def_in)
{
- if (fromenv) {
- const char *value = getenv(GIT_COMMON_DIR_ENVIRONMENT);
- if (value) {
- strbuf_addstr(sb, value);
- return 1;
- }
- }
-
- return get_common_dir_noenv(sb, gitdir);
+ free(*out);
+ if (in)
+ *out = xstrdup(in);
+ else
+ *out = xstrfmt("%s/%s", base_dir, def_in);
}
-static void repo_setup_env(struct repository *repo)
+static void repo_set_commondir(struct repository *repo,
+ const char *commondir)
{
struct strbuf sb = STRBUF_INIT;
- repo->different_commondir = find_common_dir(&sb, repo->gitdir,
- !repo->ignore_env);
free(repo->commondir);
+
+ if (commondir) {
+ repo->different_commondir = 1;
+ repo->commondir = xstrdup(commondir);
+ return;
+ }
+
+ repo->different_commondir = get_common_dir_noenv(&sb, repo->gitdir);
repo->commondir = strbuf_detach(&sb, NULL);
- free(repo->objectdir);
- repo->objectdir = git_path_from_env(DB_ENVIRONMENT, repo->commondir,
- "objects", !repo->ignore_env);
- free(repo->graft_file);
- repo->graft_file = git_path_from_env(GRAFT_ENVIRONMENT, repo->commondir,
- "info/grafts", !repo->ignore_env);
- free(repo->index_file);
- repo->index_file = git_path_from_env(INDEX_ENVIRONMENT, repo->gitdir,
- "index", !repo->ignore_env);
}
-void repo_set_gitdir(struct repository *repo, const char *path)
+void repo_set_gitdir(struct repository *repo,
+ const char *root,
+ const struct set_gitdir_args *o)
{
- const char *gitfile = read_gitfile(path);
+ const char *gitfile = read_gitfile(root);
+ /*
+ * repo->gitdir is saved because the caller could pass "root"
+ * that also points to repo->gitdir. We want to keep it alive
+ * until after xstrdup(root). Then we can free it.
+ */
char *old_gitdir = repo->gitdir;
- repo->gitdir = xstrdup(gitfile ? gitfile : path);
- repo_setup_env(repo);
-
+ repo->gitdir = xstrdup(gitfile ? gitfile : root);
free(old_gitdir);
+
+ repo_set_commondir(repo, o->commondir);
+ expand_base_dir(&repo->objects->objectdir, o->object_dir,
+ repo->commondir, "objects");
+ free(repo->objects->alternate_db);
+ repo->objects->alternate_db = xstrdup_or_null(o->alternate_db);
+ expand_base_dir(&repo->graft_file, o->graft_file,
+ repo->commondir, "info/grafts");
+ expand_base_dir(&repo->index_file, o->index_file,
+ repo->gitdir, "index");
}
void repo_set_hash_algo(struct repository *repo, int hash_algo)
int error = 0;
char *abspath = NULL;
const char *resolved_gitdir;
+ struct set_gitdir_args args = { NULL };
abspath = real_pathdup(gitdir, 0);
if (!abspath) {
goto out;
}
- repo_set_gitdir(repo, resolved_gitdir);
+ repo_set_gitdir(repo, resolved_gitdir, &args);
out:
free(abspath);
* Initialize 'repo' based on the provided 'gitdir'.
* Return 0 upon success and a non-zero value upon failure.
*/
-int repo_init(struct repository *repo, const char *gitdir, const char *worktree)
+static int repo_init(struct repository *repo,
+ const char *gitdir,
+ const char *worktree)
{
struct repository_format format;
memset(repo, 0, sizeof(*repo));
- repo->ignore_env = 1;
+ repo->objects = raw_object_store_new();
if (repo_init_gitdir(repo, gitdir))
goto error;
{
FREE_AND_NULL(repo->gitdir);
FREE_AND_NULL(repo->commondir);
- FREE_AND_NULL(repo->objectdir);
FREE_AND_NULL(repo->graft_file);
FREE_AND_NULL(repo->index_file);
FREE_AND_NULL(repo->worktree);
FREE_AND_NULL(repo->submodule_prefix);
+ raw_object_store_clear(repo->objects);
+ FREE_AND_NULL(repo->objects);
+
if (repo->config) {
git_configset_clear(repo->config);
FREE_AND_NULL(repo->config);
#define REPOSITORY_H
struct config_set;
+struct git_hash_algo;
struct index_state;
+struct raw_object_store;
struct submodule_cache;
-struct git_hash_algo;
struct repository {
/* Environment */
char *commondir;
/*
- * Path to the repository's object store.
- * Cannot be NULL after initialization.
+ * Holds any information related to accessing the raw object content.
*/
- char *objectdir;
+ struct raw_object_store *objects;
/*
* Path to the repository's graft file.
const struct git_hash_algo *hash_algo;
/* Configurations */
- /*
- * Bit used during initialization to indicate if repository state (like
- * the location of the 'objectdir') should be read from the
- * environment. By default this bit will be set at the begining of
- * 'repo_init()' so that all repositories will ignore the environment.
- * The exception to this is 'the_repository', which doesn't go through
- * the normal 'repo_init()' process.
- */
- unsigned ignore_env:1;
/* Indicate if a repository has a different 'commondir' from 'gitdir' */
unsigned different_commondir:1;
extern struct repository *the_repository;
-extern void repo_set_gitdir(struct repository *repo, const char *path);
+/*
+ * Define a custom repository layout. Any field can be NULL, which
+ * will default back to the path according to the default layout.
+ */
+struct set_gitdir_args {
+ const char *commondir;
+ const char *object_dir;
+ const char *graft_file;
+ const char *index_file;
+ const char *alternate_db;
+};
+
+extern void repo_set_gitdir(struct repository *repo,
+ const char *root,
+ const struct set_gitdir_args *extra_args);
extern void repo_set_worktree(struct repository *repo, const char *path);
extern void repo_set_hash_algo(struct repository *repo, int algo);
-extern int repo_init(struct repository *repo, const char *gitdir, const char *worktree);
+extern void initialize_the_repository(void);
extern int repo_submodule_init(struct repository *submodule,
struct repository *superproject,
const char *path);
break;
i = ce_stage(ce) - 1;
if (!mmfile[i].ptr) {
- mmfile[i].ptr = read_sha1_file(ce->oid.hash, &type,
- &size);
+ mmfile[i].ptr = read_object_file(&ce->oid, &type,
+ &size);
mmfile[i].size = size;
}
}
if (!lost->util)
lost->util = xcalloc(1, sizeof(*ui));
ui = lost->util;
- hashcpy(ui->sha1[stage - 1], ce->oid.hash);
+ oidcpy(&ui->oid[stage - 1], &ce->oid);
ui->mode[stage - 1] = ce->ce_mode;
}
for (i = 0; i < 3; i++) {
if (!ui->mode[i])
continue;
- strbuf_add(sb, ui->sha1[i], 20);
+ strbuf_add(sb, ui->oid[i].hash, the_hash_algo->rawsz);
}
}
}
size_t len;
char *endptr;
int i;
+ const unsigned rawsz = the_hash_algo->rawsz;
resolve_undo = xcalloc(1, sizeof(*resolve_undo));
resolve_undo->strdup_strings = 1;
for (i = 0; i < 3; i++) {
if (!ui->mode[i])
continue;
- if (size < 20)
+ if (size < rawsz)
goto error;
- hashcpy(ui->sha1[i], (const unsigned char *)data);
- size -= 20;
- data += 20;
+ memcpy(ui->oid[i].hash, (const unsigned char *)data, rawsz);
+ size -= rawsz;
+ data += rawsz;
}
}
return resolve_undo;
struct cache_entry *nce;
if (!ru->mode[i])
continue;
- nce = make_cache_entry(ru->mode[i], ru->sha1[i],
+ nce = make_cache_entry(ru->mode[i], ru->oid[i].hash,
name, i + 1, 0);
if (matched)
nce->ce_flags |= CE_MATCHED;
struct resolve_undo_info {
unsigned int mode[3];
- unsigned char sha1[3][20];
+ struct object_id oid[3];
};
extern void record_resolve_undo(struct index_state *, struct cache_entry *);
if (!trace_want(&trace_default_key))
return;
- strbuf_addf(&buf, "trace: run_command:");
+ strbuf_addstr(&buf, "trace: run_command:");
if (cp->dir) {
strbuf_addstr(&buf, " cd ");
sq_quote_buf_pretty(&buf, cp->dir);
die("bad %s argument: %s", opt->long_name, arg);
}
-static void feed_object(const unsigned char *sha1, FILE *fh, int negative)
+static void feed_object(const struct object_id *oid, FILE *fh, int negative)
{
- if (negative && !has_sha1_file(sha1))
+ if (negative && !has_sha1_file(oid->hash))
return;
if (negative)
putc('^', fh);
- fputs(sha1_to_hex(sha1), fh);
+ fputs(oid_to_hex(oid), fh);
putc('\n', fh);
}
*/
po_in = xfdopen(po.in, "w");
for (i = 0; i < extra->nr; i++)
- feed_object(extra->oid[i].hash, po_in, 1);
+ feed_object(&extra->oid[i], po_in, 1);
while (refs) {
if (!is_null_oid(&refs->old_oid))
- feed_object(refs->old_oid.hash, po_in, 1);
+ feed_object(&refs->old_oid, po_in, 1);
if (!is_null_oid(&refs->new_oid))
- feed_object(refs->new_oid.hash, po_in, 0);
+ feed_object(&refs->new_oid, po_in, 0);
refs = refs->next;
}
static const char *short_commit_name(struct commit *commit)
{
- return find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV);
+ return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
}
static int get_message(struct commit *commit, struct commit_message *out)
commit_list_insert(current_head, &parents);
}
- if (write_cache_as_tree(tree.hash, 0, NULL)) {
+ if (write_cache_as_tree(&tree, 0, NULL)) {
res = error(_("git write-tree failed to write a tree"));
goto out;
}
* that represents the "current" state for merge-recursive
* to work on.
*/
- if (write_cache_as_tree(head.hash, 0, NULL))
+ if (write_cache_as_tree(&head, 0, NULL))
return error(_("your index file is unmerged."));
} else {
unborn = get_oid("HEAD", &head);
if (!get_oid(name, &oid)) {
if (!lookup_commit_reference_gently(&oid, 1)) {
- enum object_type type = sha1_object_info(oid.hash, NULL);
+ enum object_type type = oid_object_info(&oid,
+ NULL);
return error(_("%s: can't cherry-pick a %s"),
name, type_name(type));
}
#include "cache.h"
+#include "repository.h"
#include "refs.h"
#include "object.h"
#include "commit.h"
#include "tag.h"
#include "packfile.h"
+#include "object-store.h"
/*
* Create the file "path" by writing to a temporary file and renaming
objdir = get_object_directory();
objdirlen = strlen(objdir);
- prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
+ for (p = get_packed_git(the_repository); p; p = p->next) {
/* we ignore things on alternate path since they are
* not available to the pullers in general.
*/
}
num_pack = i;
info = xcalloc(num_pack, sizeof(struct pack_info *));
- for (i = 0, p = packed_git; p; p = p->next) {
+ for (i = 0, p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
info[i] = xcalloc(1, sizeof(struct pack_info));
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
if (!gitdir)
gitdir = DEFAULT_GIT_DIR_ENVIRONMENT;
- repo_set_gitdir(the_repository, gitdir);
- setup_git_env();
+ setup_git_env(gitdir);
}
if (startup_info->have_repository)
repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
#include "pack-revindex.h"
#include "sha1-lookup.h"
#include "bulk-checkin.h"
+#include "repository.h"
#include "streaming.h"
#include "dir.h"
#include "list.h"
#include "quote.h"
#include "packfile.h"
#include "fetch-object.h"
+#include "object-store.h"
+
+/* The maximum size for an object header. */
+#define MAX_HEADER_LEN 32
const unsigned char null_sha1[GIT_MAX_RAWSZ];
const struct object_id null_oid;
}
}
-void sha1_file_name(struct strbuf *buf, const unsigned char *sha1)
+void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned char *sha1)
{
- strbuf_addstr(buf, get_object_directory());
+ strbuf_addstr(buf, r->objects->objectdir);
strbuf_addch(buf, '/');
fill_sha1_path(buf, sha1);
}
return buf->buf;
}
-struct alternate_object_database *alt_odb_list;
-static struct alternate_object_database **alt_odb_tail;
-
/*
* Return non-zero iff the path is usable as an alternate object database.
*/
-static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
+static int alt_odb_usable(struct raw_object_store *o,
+ struct strbuf *path,
+ const char *normalized_objdir)
{
struct alternate_object_database *alt;
* Prevent the common mistake of listing the same
* thing twice, or object directory itself.
*/
- for (alt = alt_odb_list; alt; alt = alt->next) {
+ for (alt = o->alt_odb_list; alt; alt = alt->next) {
if (!fspathcmp(path->buf, alt->path))
return 0;
}
* SHA1, an extra slash for the first level indirection, and the
* terminating NUL.
*/
-static void read_info_alternates(const char * relative_base, int depth);
-static int link_alt_odb_entry(const char *entry, const char *relative_base,
- int depth, const char *normalized_objdir)
+static void read_info_alternates(struct repository *r,
+ const char *relative_base,
+ int depth);
+static int link_alt_odb_entry(struct repository *r, const char *entry,
+ const char *relative_base, int depth, const char *normalized_objdir)
{
struct alternate_object_database *ent;
struct strbuf pathbuf = STRBUF_INIT;
while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
strbuf_setlen(&pathbuf, pathbuf.len - 1);
- if (!alt_odb_usable(&pathbuf, normalized_objdir)) {
+ if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir)) {
strbuf_release(&pathbuf);
return -1;
}
ent = alloc_alt_odb(pathbuf.buf);
/* add the alternate entry */
- *alt_odb_tail = ent;
- alt_odb_tail = &(ent->next);
+ *r->objects->alt_odb_tail = ent;
+ r->objects->alt_odb_tail = &(ent->next);
ent->next = NULL;
/* recursively add alternates */
- read_info_alternates(pathbuf.buf, depth + 1);
+ read_info_alternates(r, pathbuf.buf, depth + 1);
strbuf_release(&pathbuf);
return 0;
return end;
}
-static void link_alt_odb_entries(const char *alt, int sep,
- const char *relative_base, int depth)
+static void link_alt_odb_entries(struct repository *r, const char *alt,
+ int sep, const char *relative_base, int depth)
{
struct strbuf objdirbuf = STRBUF_INIT;
struct strbuf entry = STRBUF_INIT;
return;
}
- strbuf_add_absolute_path(&objdirbuf, get_object_directory());
+ strbuf_add_absolute_path(&objdirbuf, r->objects->objectdir);
if (strbuf_normalize_path(&objdirbuf) < 0)
die("unable to normalize object directory: %s",
objdirbuf.buf);
alt = parse_alt_odb_entry(alt, sep, &entry);
if (!entry.len)
continue;
- link_alt_odb_entry(entry.buf, relative_base, depth, objdirbuf.buf);
+ link_alt_odb_entry(r, entry.buf,
+ relative_base, depth, objdirbuf.buf);
}
strbuf_release(&entry);
strbuf_release(&objdirbuf);
}
-static void read_info_alternates(const char * relative_base, int depth)
+static void read_info_alternates(struct repository *r,
+ const char *relative_base,
+ int depth)
{
char *path;
struct strbuf buf = STRBUF_INIT;
return;
}
- link_alt_odb_entries(buf.buf, '\n', relative_base, depth);
+ link_alt_odb_entries(r, buf.buf, '\n', relative_base, depth);
strbuf_release(&buf);
free(path);
}
fprintf_or_die(out, "%s\n", reference);
if (commit_lock_file(&lock))
die_errno("unable to move new alternates file into place");
- if (alt_odb_tail)
- link_alt_odb_entries(reference, '\n', NULL, 0);
+ if (the_repository->objects->alt_odb_tail)
+ link_alt_odb_entries(the_repository, reference,
+ '\n', NULL, 0);
}
free(alts);
}
* Make sure alternates are initialized, or else our entry may be
* overwritten when they are.
*/
- prepare_alt_odb();
+ prepare_alt_odb(the_repository);
- link_alt_odb_entries(reference, '\n', NULL, 0);
+ link_alt_odb_entries(the_repository, reference,
+ '\n', NULL, 0);
}
/*
struct alternate_object_database *ent;
int r = 0;
- prepare_alt_odb();
- for (ent = alt_odb_list; ent; ent = ent->next) {
+ prepare_alt_odb(the_repository);
+ for (ent = the_repository->objects->alt_odb_list; ent; ent = ent->next) {
r = fn(ent, cb);
if (r)
break;
return r;
}
-void prepare_alt_odb(void)
+void prepare_alt_odb(struct repository *r)
{
- const char *alt;
-
- if (alt_odb_tail)
+ if (r->objects->alt_odb_tail)
return;
- alt = getenv(ALTERNATE_DB_ENVIRONMENT);
+ r->objects->alt_odb_tail = &r->objects->alt_odb_list;
+ link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0);
- alt_odb_tail = &alt_odb_list;
- link_alt_odb_entries(alt, PATH_SEP, NULL, 0);
-
- read_info_alternates(get_object_directory(), 0);
+ read_info_alternates(r, r->objects->objectdir, 0);
}
/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
static struct strbuf buf = STRBUF_INIT;
strbuf_reset(&buf);
- sha1_file_name(&buf, sha1);
+ sha1_file_name(the_repository, &buf, sha1);
return check_and_freshen_file(buf.buf, freshen);
}
static int check_and_freshen_nonlocal(const unsigned char *sha1, int freshen)
{
struct alternate_object_database *alt;
- prepare_alt_odb();
- for (alt = alt_odb_list; alt; alt = alt->next) {
+ prepare_alt_odb(the_repository);
+ for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) {
const char *path = alt_sha1_path(alt, sha1);
if (check_and_freshen_file(path, freshen))
return 1;
* With "map" == NULL, try reading the object named with "sha1" using
* the streaming interface and rehash it to do the same.
*/
-int check_sha1_signature(const unsigned char *sha1, void *map,
- unsigned long size, const char *type)
+int check_object_signature(const struct object_id *oid, void *map,
+ unsigned long size, const char *type)
{
struct object_id real_oid;
enum object_type obj_type;
struct git_istream *st;
git_hash_ctx c;
- char hdr[32];
+ char hdr[MAX_HEADER_LEN];
int hdrlen;
if (map) {
hash_object_file(map, size, type, &real_oid);
- return hashcmp(sha1, real_oid.hash) ? -1 : 0;
+ return oidcmp(oid, &real_oid) ? -1 : 0;
}
- st = open_istream(sha1, &obj_type, &size, NULL);
+ st = open_istream(oid, &obj_type, &size, NULL);
if (!st)
return -1;
}
the_hash_algo->final_fn(real_oid.hash, &c);
close_istream(st);
- return hashcmp(sha1, real_oid.hash) ? -1 : 0;
+ return oidcmp(oid, &real_oid) ? -1 : 0;
}
int git_open_cloexec(const char *name, int flags)
* Note that it may point to static storage and is only valid until another
* call to sha1_file_name(), etc.
*/
-static int stat_sha1_file(const unsigned char *sha1, struct stat *st,
- const char **path)
+static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
+ struct stat *st, const char **path)
{
struct alternate_object_database *alt;
static struct strbuf buf = STRBUF_INIT;
strbuf_reset(&buf);
- sha1_file_name(&buf, sha1);
+ sha1_file_name(r, &buf, sha1);
*path = buf.buf;
if (!lstat(*path, st))
return 0;
- prepare_alt_odb();
+ prepare_alt_odb(r);
errno = ENOENT;
- for (alt = alt_odb_list; alt; alt = alt->next) {
+ for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
*path = alt_sha1_path(alt, sha1);
if (!lstat(*path, st))
return 0;
* Like stat_sha1_file(), but actually open the object and return the
* descriptor. See the caveats on the "path" parameter above.
*/
-static int open_sha1_file(const unsigned char *sha1, const char **path)
+static int open_sha1_file(struct repository *r,
+ const unsigned char *sha1, const char **path)
{
int fd;
struct alternate_object_database *alt;
static struct strbuf buf = STRBUF_INIT;
strbuf_reset(&buf);
- sha1_file_name(&buf, sha1);
+ sha1_file_name(r, &buf, sha1);
*path = buf.buf;
fd = git_open(*path);
return fd;
most_interesting_errno = errno;
- prepare_alt_odb();
- for (alt = alt_odb_list; alt; alt = alt->next) {
+ prepare_alt_odb(r);
+ for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
*path = alt_sha1_path(alt, sha1);
fd = git_open(*path);
if (fd >= 0)
* Map the loose object at "path" if it is not NULL, or the path found by
* searching for a loose object named "sha1".
*/
-static void *map_sha1_file_1(const char *path,
- const unsigned char *sha1,
- unsigned long *size)
+static void *map_sha1_file_1(struct repository *r, const char *path,
+ const unsigned char *sha1, unsigned long *size)
{
void *map;
int fd;
if (path)
fd = git_open(path);
else
- fd = open_sha1_file(sha1, &path);
+ fd = open_sha1_file(r, sha1, &path);
map = NULL;
if (fd >= 0) {
struct stat st;
return map;
}
-void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
+void *map_sha1_file(struct repository *r,
+ const unsigned char *sha1, unsigned long *size)
{
- return map_sha1_file_1(NULL, sha1, size);
+ return map_sha1_file_1(r, NULL, sha1, size);
}
static int unpack_sha1_short_header(git_zstream *stream,
return parse_sha1_header_extended(hdr, &oi, 0);
}
-static int sha1_loose_object_info(const unsigned char *sha1,
- struct object_info *oi,
- int flags)
+static int sha1_loose_object_info(struct repository *r,
+ const unsigned char *sha1,
+ struct object_info *oi, int flags)
{
int status = 0;
unsigned long mapsize;
void *map;
git_zstream stream;
- char hdr[32];
+ char hdr[MAX_HEADER_LEN];
struct strbuf hdrbuf = STRBUF_INIT;
unsigned long size_scratch;
if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
const char *path;
struct stat st;
- if (stat_sha1_file(sha1, &st, &path) < 0)
+ if (stat_sha1_file(r, sha1, &st, &path) < 0)
return -1;
if (oi->disk_sizep)
*oi->disk_sizep = st.st_size;
return 0;
}
- map = map_sha1_file(sha1, &mapsize);
+ map = map_sha1_file(r, sha1, &mapsize);
if (!map)
return -1;
int fetch_if_missing = 1;
-int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
+int oid_object_info_extended(const struct object_id *oid, struct object_info *oi, unsigned flags)
{
static struct object_info blank_oi = OBJECT_INFO_INIT;
struct pack_entry e;
int rtype;
- const unsigned char *real = (flags & OBJECT_INFO_LOOKUP_REPLACE) ?
- lookup_replace_object(sha1) :
- sha1;
+ const struct object_id *real = oid;
int already_retried = 0;
- if (is_null_sha1(real))
+ if (flags & OBJECT_INFO_LOOKUP_REPLACE)
+ real = lookup_replace_object(oid);
+
+ if (is_null_oid(real))
return -1;
if (!oi)
oi = &blank_oi;
if (!(flags & OBJECT_INFO_SKIP_CACHED)) {
- struct cached_object *co = find_cached_object(real);
+ struct cached_object *co = find_cached_object(real->hash);
if (co) {
if (oi->typep)
*(oi->typep) = co->type;
}
while (1) {
- if (find_pack_entry(real, &e))
+ if (find_pack_entry(the_repository, real->hash, &e))
break;
+ if (flags & OBJECT_INFO_IGNORE_LOOSE)
+ return -1;
+
/* Most likely it's a loose object. */
- if (!sha1_loose_object_info(real, oi, flags))
+ if (!sha1_loose_object_info(the_repository, real->hash, oi, flags))
return 0;
/* Not a loose object; someone else may have just packed it. */
if (!(flags & OBJECT_INFO_QUICK)) {
- reprepare_packed_git();
- if (find_pack_entry(real, &e))
+ reprepare_packed_git(the_repository);
+ if (find_pack_entry(the_repository, real->hash, &e))
break;
}
* TODO Investigate haveing fetch_object() return
* TODO error/success and stopping the music here.
*/
- fetch_object(repository_format_partial_clone, real);
+ fetch_object(repository_format_partial_clone, real->hash);
already_retried = 1;
continue;
}
return 0;
rtype = packed_object_info(e.p, e.offset, oi);
if (rtype < 0) {
- mark_bad_packed_object(e.p, real);
- return sha1_object_info_extended(real, oi, 0);
+ mark_bad_packed_object(e.p, real->hash);
+ return oid_object_info_extended(real, oi, 0);
} else if (oi->whence == OI_PACKED) {
oi->u.packed.offset = e.offset;
oi->u.packed.pack = e.p;
}
/* returns enum object_type or negative */
-int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
+int oid_object_info(const struct object_id *oid, unsigned long *sizep)
{
enum object_type type;
struct object_info oi = OBJECT_INFO_INIT;
oi.typep = &type;
oi.sizep = sizep;
- if (sha1_object_info_extended(sha1, &oi,
- OBJECT_INFO_LOOKUP_REPLACE) < 0)
+ if (oid_object_info_extended(oid, &oi,
+ OBJECT_INFO_LOOKUP_REPLACE) < 0)
return -1;
return type;
}
static void *read_object(const unsigned char *sha1, enum object_type *type,
unsigned long *size)
{
+ struct object_id oid;
struct object_info oi = OBJECT_INFO_INIT;
void *content;
oi.typep = type;
oi.sizep = size;
oi.contentp = &content;
- if (sha1_object_info_extended(sha1, &oi, 0) < 0)
+ hashcpy(oid.hash, sha1);
+
+ if (oid_object_info_extended(&oid, &oi, 0) < 0)
return NULL;
return content;
}
* deal with them should arrange to call read_object() and give error
* messages themselves.
*/
-void *read_sha1_file_extended(const unsigned char *sha1,
- enum object_type *type,
- unsigned long *size,
- int lookup_replace)
+void *read_object_file_extended(const struct object_id *oid,
+ enum object_type *type,
+ unsigned long *size,
+ int lookup_replace)
{
void *data;
const struct packed_git *p;
const char *path;
struct stat st;
- const unsigned char *repl = lookup_replace ? lookup_replace_object(sha1)
- : sha1;
+ const struct object_id *repl = lookup_replace ? lookup_replace_object(oid)
+ : oid;
errno = 0;
- data = read_object(repl, type, size);
+ data = read_object(repl->hash, type, size);
if (data)
return data;
if (errno && errno != ENOENT)
- die_errno("failed to read object %s", sha1_to_hex(sha1));
+ die_errno("failed to read object %s", oid_to_hex(oid));
/* die if we replaced an object with one that does not exist */
- if (repl != sha1)
+ if (repl != oid)
die("replacement %s not found for %s",
- sha1_to_hex(repl), sha1_to_hex(sha1));
+ oid_to_hex(repl), oid_to_hex(oid));
- if (!stat_sha1_file(repl, &st, &path))
+ if (!stat_sha1_file(the_repository, repl->hash, &st, &path))
die("loose object %s (stored in %s) is corrupt",
- sha1_to_hex(repl), path);
+ oid_to_hex(repl), path);
- if ((p = has_packed_and_bad(repl)) != NULL)
+ if ((p = has_packed_and_bad(repl->hash)) != NULL)
die("packed object %s (stored in %s) is corrupt",
- sha1_to_hex(repl), p->pack_name);
+ oid_to_hex(repl), p->pack_name);
return NULL;
}
-void *read_object_with_reference(const unsigned char *sha1,
+void *read_object_with_reference(const struct object_id *oid,
const char *required_type_name,
unsigned long *size,
- unsigned char *actual_sha1_return)
+ struct object_id *actual_oid_return)
{
enum object_type type, required_type;
void *buffer;
unsigned long isize;
- unsigned char actual_sha1[20];
+ struct object_id actual_oid;
required_type = type_from_string(required_type_name);
- hashcpy(actual_sha1, sha1);
+ oidcpy(&actual_oid, oid);
while (1) {
int ref_length = -1;
const char *ref_type = NULL;
- buffer = read_sha1_file(actual_sha1, &type, &isize);
+ buffer = read_object_file(&actual_oid, &type, &isize);
if (!buffer)
return NULL;
if (type == required_type) {
*size = isize;
- if (actual_sha1_return)
- hashcpy(actual_sha1_return, actual_sha1);
+ if (actual_oid_return)
+ oidcpy(actual_oid_return, &actual_oid);
return buffer;
}
/* Handle references */
}
ref_length = strlen(ref_type);
- if (ref_length + 40 > isize ||
+ if (ref_length + GIT_SHA1_HEXSZ > isize ||
memcmp(buffer, ref_type, ref_length) ||
- get_sha1_hex((char *) buffer + ref_length, actual_sha1)) {
+ get_oid_hex((char *) buffer + ref_length, &actual_oid)) {
free(buffer);
return NULL;
}
free(buffer);
/* Now we have the ID of the referred-to object in
- * actual_sha1. Check again. */
+ * actual_oid. Check again. */
}
}
int hash_object_file(const void *buf, unsigned long len, const char *type,
struct object_id *oid)
{
- char hdr[32];
+ char hdr[MAX_HEADER_LEN];
int hdrlen = sizeof(hdr);
write_object_file_prepare(buf, len, type, oid, hdr, &hdrlen);
return 0;
static struct strbuf filename = STRBUF_INIT;
strbuf_reset(&filename);
- sha1_file_name(&filename, oid->hash);
+ sha1_file_name(the_repository, &filename, oid->hash);
fd = create_tmpfile(&tmp_file, filename.buf);
if (fd < 0) {
static int freshen_packed_object(const unsigned char *sha1)
{
struct pack_entry e;
- if (!find_pack_entry(sha1, &e))
+ if (!find_pack_entry(the_repository, sha1, &e))
return 0;
if (e.p->freshened)
return 1;
int write_object_file(const void *buf, unsigned long len, const char *type,
struct object_id *oid)
{
- char hdr[32];
+ char hdr[MAX_HEADER_LEN];
int hdrlen = sizeof(hdr);
/* Normally if we have it in the pack then we do not bother writing
int hdrlen, status = 0;
/* type string, SP, %lu of the length plus NUL must fit this */
- hdrlen = strlen(type) + 32;
+ hdrlen = strlen(type) + MAX_HEADER_LEN;
header = xmalloc(hdrlen);
write_object_file_prepare(buf, len, type, oid, header, &hdrlen);
void *buf;
unsigned long len;
enum object_type type;
- char hdr[32];
+ char hdr[MAX_HEADER_LEN];
int hdrlen;
int ret;
int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
{
+ struct object_id oid;
if (!startup_info->have_repository)
return 0;
- return sha1_object_info_extended(sha1, NULL,
- flags | OBJECT_INFO_SKIP_CACHED) >= 0;
+ hashcpy(oid.hash, sha1);
+ return oid_object_info_extended(&oid, NULL,
+ flags | OBJECT_INFO_SKIP_CACHED) >= 0;
}
int has_object_file(const struct object_id *oid)
enum object_type type, const char *path,
unsigned flags)
{
- return index_bulk_checkin(oid->hash, fd, size, type, path, flags);
+ return index_bulk_checkin(oid, fd, size, type, path, flags);
}
int index_fd(struct object_id *oid, int fd, struct stat *st,
return 0;
}
-void assert_sha1_type(const unsigned char *sha1, enum object_type expect)
+void assert_oid_type(const struct object_id *oid, enum object_type expect)
{
- enum object_type type = sha1_object_info(sha1, NULL);
+ enum object_type type = oid_object_info(oid, NULL);
if (type < 0)
- die("%s is not a valid object", sha1_to_hex(sha1));
+ die("%s is not a valid object", oid_to_hex(oid));
if (type != expect)
- die("%s is not a valid '%s' object", sha1_to_hex(sha1),
+ die("%s is not a valid '%s' object", oid_to_hex(oid),
type_name(expect));
}
}
int read_loose_object(const char *path,
- const unsigned char *expected_sha1,
+ const struct object_id *expected_oid,
enum object_type *type,
unsigned long *size,
void **contents)
void *map = NULL;
unsigned long mapsize;
git_zstream stream;
- char hdr[32];
+ char hdr[MAX_HEADER_LEN];
*contents = NULL;
- map = map_sha1_file_1(path, NULL, &mapsize);
+ map = map_sha1_file_1(the_repository, path, NULL, &mapsize);
if (!map) {
error_errno("unable to mmap %s", path);
goto out;
}
if (*type == OBJ_BLOB) {
- if (check_stream_sha1(&stream, hdr, *size, path, expected_sha1) < 0)
+ if (check_stream_sha1(&stream, hdr, *size, path, expected_oid->hash) < 0)
goto out;
} else {
- *contents = unpack_sha1_rest(&stream, hdr, *size, expected_sha1);
+ *contents = unpack_sha1_rest(&stream, hdr, *size, expected_oid->hash);
if (!*contents) {
error("unable to unpack contents of %s", path);
git_inflate_end(&stream);
goto out;
}
- if (check_sha1_signature(expected_sha1, *contents,
+ if (check_object_signature(expected_oid, *contents,
*size, type_name(*type))) {
error("sha1 mismatch for %s (expected %s)", path,
- sha1_to_hex(expected_sha1));
+ oid_to_hex(expected_oid));
free(*contents);
goto out;
}
#include "dir.h"
#include "sha1-array.h"
#include "packfile.h"
+#include "object-store.h"
+#include "repository.h"
static int get_oid_oneline(const char *, struct object_id *, struct commit_list *);
*/
fakeent = alloc_alt_odb(get_object_directory());
}
- fakeent->next = alt_odb_list;
+ fakeent->next = the_repository->objects->alt_odb_list;
for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
int pos;
static void unique_in_pack(struct packed_git *p,
struct disambiguate_state *ds)
{
- uint32_t num, last, i, first = 0;
+ uint32_t num, i, first = 0;
const struct object_id *current = NULL;
if (open_pack_index(p) || !p->num_objects)
return;
num = p->num_objects;
- last = num;
- while (first < last) {
- uint32_t mid = first + (last - first) / 2;
- const unsigned char *current;
- int cmp;
-
- current = nth_packed_object_sha1(p, mid);
- cmp = hashcmp(ds->bin_pfx.hash, current);
- if (!cmp) {
- first = mid;
- break;
- }
- if (cmp > 0) {
- first = mid+1;
- continue;
- }
- last = mid;
- }
+ bsearch_pack(&ds->bin_pfx, p, &first);
/*
* At this point, "first" is the location of the lowest object
{
struct packed_git *p;
- prepare_packed_git();
- for (p = packed_git; p && !ds->ambiguous; p = p->next)
+ for (p = get_packed_git(the_repository); p && !ds->ambiguous;
+ p = p->next)
unique_in_pack(p, ds);
}
static int disambiguate_commit_only(const struct object_id *oid, void *cb_data_unused)
{
- int kind = sha1_object_info(oid->hash, NULL);
+ int kind = oid_object_info(oid, NULL);
return kind == OBJ_COMMIT;
}
struct object *obj;
int kind;
- kind = sha1_object_info(oid->hash, NULL);
+ kind = oid_object_info(oid, NULL);
if (kind == OBJ_COMMIT)
return 1;
if (kind != OBJ_TAG)
static int disambiguate_tree_only(const struct object_id *oid, void *cb_data_unused)
{
- int kind = sha1_object_info(oid->hash, NULL);
+ int kind = oid_object_info(oid, NULL);
return kind == OBJ_TREE;
}
struct object *obj;
int kind;
- kind = sha1_object_info(oid->hash, NULL);
+ kind = oid_object_info(oid, NULL);
if (kind == OBJ_TREE || kind == OBJ_COMMIT)
return 1;
if (kind != OBJ_TAG)
static int disambiguate_blob_only(const struct object_id *oid, void *cb_data_unused)
{
- int kind = sha1_object_info(oid->hash, NULL);
+ int kind = oid_object_info(oid, NULL);
return kind == OBJ_BLOB;
}
ds->len = len;
ds->hex_pfx[len] = '\0';
- prepare_alt_odb();
+ prepare_alt_odb(the_repository);
return 0;
}
if (ds->fn && !ds->fn(oid, ds->cb_data))
return 0;
- type = sha1_object_info(oid->hash, NULL);
+ type = oid_object_info(oid, NULL);
if (type == OBJ_COMMIT) {
struct commit *commit = lookup_commit(oid);
if (commit) {
}
advise(" %s %s%s",
- find_unique_abbrev(oid->hash, DEFAULT_ABBREV),
+ find_unique_abbrev(oid, DEFAULT_ABBREV),
type_name(type) ? type_name(type) : "unknown type",
desc.buf);
unsigned int init_len;
unsigned int cur_len;
char *hex;
- const unsigned char *hash;
+ const struct object_id *oid;
};
static inline char get_hex_char_from_oid(const struct object_id *oid,
struct min_abbrev_data *mad)
{
int match = 0;
- uint32_t num, last, first = 0;
+ uint32_t num, first = 0;
struct object_id oid;
+ const struct object_id *mad_oid;
if (open_pack_index(p) || !p->num_objects)
return;
num = p->num_objects;
- last = num;
- while (first < last) {
- uint32_t mid = first + (last - first) / 2;
- const unsigned char *current;
- int cmp;
-
- current = nth_packed_object_sha1(p, mid);
- cmp = hashcmp(mad->hash, current);
- if (!cmp) {
- match = 1;
- first = mid;
- break;
- }
- if (cmp > 0) {
- first = mid + 1;
- continue;
- }
- last = mid;
- }
+ mad_oid = mad->oid;
+ match = bsearch_pack(mad_oid, p, &first);
/*
* first is now the position in the packfile where we would insert
{
struct packed_git *p;
- prepare_packed_git();
- for (p = packed_git; p; p = p->next)
+ for (p = get_packed_git(the_repository); p; p = p->next)
find_abbrev_len_for_pack(p, mad);
}
-int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
+int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len)
{
struct disambiguate_state ds;
struct min_abbrev_data mad;
len = FALLBACK_DEFAULT_ABBREV;
}
- sha1_to_hex_r(hex, sha1);
+ oid_to_hex_r(hex, oid);
if (len == GIT_SHA1_HEXSZ || !len)
return GIT_SHA1_HEXSZ;
mad.init_len = len;
mad.cur_len = len;
mad.hex = hex;
- mad.hash = sha1;
+ mad.oid = oid;
find_abbrev_len_packed(&mad);
return mad.cur_len;
}
-const char *find_unique_abbrev(const unsigned char *sha1, int len)
+const char *find_unique_abbrev(const struct object_id *oid, int len)
{
static int bufno;
static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
char *hex = hexbuffer[bufno];
bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
- find_unique_abbrev_r(hex, sha1, len);
+ find_unique_abbrev_r(hex, oid, len);
return hex;
}
if (is_missing_file_error(errno)) {
char *fullname = xstrfmt("%s%s", prefix, filename);
- if (!get_tree_entry(tree_oid->hash, fullname,
- oid.hash, &mode)) {
+ if (!get_tree_entry(tree_oid, fullname, &oid, &mode)) {
die("Path '%s' exists, but not '%s'.\n"
"Did you mean '%.*s:%s' aka '%.*s:./%s'?",
fullname,
filename, oid->hash, &oc->symlink_path,
&oc->mode);
} else {
- ret = get_tree_entry(tree_oid.hash, filename,
- oid->hash, &oc->mode);
+ ret = get_tree_entry(&tree_oid, filename, oid,
+ &oc->mode);
if (ret && only_to_die) {
diagnose_invalid_oid_path(prefix,
filename,
strbuf_setlen(sb, sb->len + len);
}
-void strbuf_add_unique_abbrev(struct strbuf *sb, const unsigned char *sha1,
+void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
int abbrev_len)
{
int r;
strbuf_grow(sb, GIT_SHA1_HEXSZ + 1);
- r = find_unique_abbrev_r(sb->buf + sb->len, sha1, abbrev_len);
+ r = find_unique_abbrev_r(sb->buf + sb->len, oid, abbrev_len);
strbuf_setlen(sb, sb->len + r);
}
extern char strbuf_slopbuf[];
#define STRBUF_INIT { .alloc = 0, .len = 0, .buf = strbuf_slopbuf }
+/*
+ * Predeclare this here, since cache.h includes this file before it defines the
+ * struct.
+ */
+struct object_id;
+
/**
* Life Cycle Functions
* --------------------
* the strbuf `sb`.
*/
extern void strbuf_add_unique_abbrev(struct strbuf *sb,
- const unsigned char *sha1,
+ const struct object_id *oid,
int abbrev_len);
/**
*/
#include "cache.h"
#include "streaming.h"
+#include "repository.h"
+#include "object-store.h"
#include "packfile.h"
enum input_source {
typedef int (*open_istream_fn)(struct git_istream *,
struct object_info *,
- const unsigned char *,
+ const struct object_id *,
enum object_type *);
typedef int (*close_istream_fn)(struct git_istream *);
typedef ssize_t (*read_istream_fn)(struct git_istream *, char *, size_t);
#define open_method_decl(name) \
int open_istream_ ##name \
(struct git_istream *st, struct object_info *oi, \
- const unsigned char *sha1, \
+ const struct object_id *oid, \
enum object_type *type)
#define close_method_decl(name) \
return st->vtbl->read(st, buf, sz);
}
-static enum input_source istream_source(const unsigned char *sha1,
+static enum input_source istream_source(const struct object_id *oid,
enum object_type *type,
struct object_info *oi)
{
oi->typep = type;
oi->sizep = &size;
- status = sha1_object_info_extended(sha1, oi, 0);
+ status = oid_object_info_extended(oid, oi, 0);
if (status < 0)
return stream_error;
}
}
-struct git_istream *open_istream(const unsigned char *sha1,
+struct git_istream *open_istream(const struct object_id *oid,
enum object_type *type,
unsigned long *size,
struct stream_filter *filter)
{
struct git_istream *st;
struct object_info oi = OBJECT_INFO_INIT;
- const unsigned char *real = lookup_replace_object(sha1);
+ const struct object_id *real = lookup_replace_object(oid);
enum input_source src = istream_source(real, type, &oi);
if (src < 0)
static open_method_decl(loose)
{
- st->u.loose.mapped = map_sha1_file(sha1, &st->u.loose.mapsize);
+ st->u.loose.mapped = map_sha1_file(the_repository,
+ oid->hash, &st->u.loose.mapsize);
if (!st->u.loose.mapped)
return -1;
if ((unpack_sha1_header(&st->z,
static open_method_decl(incore)
{
- st->u.incore.buf = read_sha1_file_extended(sha1, type, &st->size, 0);
+ st->u.incore.buf = read_object_file_extended(oid, type, &st->size, 0);
st->u.incore.read_ptr = 0;
st->vtbl = &incore_vtbl;
ssize_t kept = 0;
int result = -1;
- st = open_istream(oid->hash, &type, &sz, filter);
+ st = open_istream(oid, &type, &sz, filter);
if (!st) {
if (filter)
free_stream_filter(filter);
/* opaque */
struct git_istream;
-extern struct git_istream *open_istream(const unsigned char *, enum object_type *, unsigned long *, struct stream_filter *);
+extern struct git_istream *open_istream(const struct object_id *, enum object_type *, unsigned long *, struct stream_filter *);
extern int close_istream(struct git_istream *);
extern ssize_t read_istream(struct git_istream *, void *, size_t);
if (submodule)
goto out;
- config = read_sha1_file(oid.hash, &type, &config_size);
+ config = read_object_file(&oid, &type, &config_size);
if (!config || type != OBJ_BLOB)
goto out;
#include "remote.h"
#include "worktree.h"
#include "parse-options.h"
+#include "object-store.h"
static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
static struct string_list changed_submodule_names = STRING_LIST_INIT_DUP;
output_header:
strbuf_addf(&sb, "Submodule %s ", path);
- strbuf_add_unique_abbrev(&sb, one->hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&sb, one, DEFAULT_ABBREV);
strbuf_addstr(&sb, (fast_backward || fast_forward) ? ".." : "...");
- strbuf_add_unique_abbrev(&sb, two->hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&sb, two, DEFAULT_ABBREV);
if (message)
strbuf_addf(&sb, " %s\n", message);
else
{
struct has_commit_data *cb = data;
- enum object_type type = sha1_object_info(oid->hash, NULL);
+ enum object_type type = oid_object_info(oid, NULL);
switch (type) {
case OBJ_COMMIT:
*
* The mtime can be changed to an absolute value:
*
- * test-chmtime =<seconds> file...
+ * test-tool chmtime =<seconds> file...
*
* Relative to the current time as returned by time(3):
*
- * test-chmtime =+<seconds> (or =-<seconds>) file...
+ * test-tool chmtime =+<seconds> (or =-<seconds>) file...
*
* Or relative to the current mtime of the file:
*
- * test-chmtime <seconds> file...
- * test-chmtime +<seconds> (or -<seconds>) file...
+ * test-tool chmtime <seconds> file...
+ * test-tool chmtime +<seconds> (or -<seconds>) file...
*
* Examples:
*
* To just print the mtime use --verbose and set the file mtime offset to 0:
*
- * test-chmtime -v +0 file
+ * test-tool chmtime -v +0 file
*
* To set the mtime to current time:
*
- * test-chmtime =+0 file
+ * test-tool chmtime =+0 file
*
*/
+#include "test-tool.h"
#include "git-compat-util.h"
#include <utime.h>
return 1;
}
-int cmd_main(int argc, const char **argv)
+int cmd__chmtime(int argc, const char **argv)
{
static int verbose;
+#include "test-tool.h"
#include "cache.h"
#include "config.h"
#include "string-list.h"
* Examples:
*
* To print the value with highest priority for key "foo.bAr Baz.rock":
- * test-config get_value "foo.bAr Baz.rock"
+ * test-tool config get_value "foo.bAr Baz.rock"
*
*/
return 0;
}
-int cmd_main(int argc, const char **argv)
+int cmd__config(int argc, const char **argv)
{
int i, val;
const char *v;
+#include "test-tool.h"
#include "cache.h"
static int rc;
#define LOWER "abcdefghijklmnopqrstuvwxyz"
#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-int cmd_main(int argc, const char **argv)
+int cmd__ctype(int argc, const char **argv)
{
TEST_CLASS(isdigit, DIGIT);
TEST_CLASS(isspace, " \n\r\t");
+#include "test-tool.h"
#include "cache.h"
static const char *usage_msg = "\n"
-" test-date relative [time_t]...\n"
-" test-date show:<format> [time_t]...\n"
-" test-date parse [date]...\n"
-" test-date approxidate [date]...\n"
-" test-date timestamp [date]...\n"
-" test-date is64bit\n"
-" test-date time_t-is64bit\n";
+" test-tool date relative [time_t]...\n"
+" test-tool date show:<format> [time_t]...\n"
+" test-tool date parse [date]...\n"
+" test-tool date approxidate [date]...\n"
+" test-tool date timestamp [date]...\n"
+" test-tool date is64bit\n"
+" test-tool date time_t-is64bit\n";
static void show_relative_dates(const char **argv, struct timeval *now)
{
}
}
-int cmd_main(int argc, const char **argv)
+int cmd__date(int argc, const char **argv)
{
struct timeval now;
const char *x;
* published by the Free Software Foundation.
*/
+#include "test-tool.h"
#include "git-compat-util.h"
#include "delta.h"
#include "cache.h"
static const char usage_str[] =
- "test-delta (-d|-p) <from_file> <data_file> <out_file>";
+ "test-tool delta (-d|-p) <from_file> <data_file> <out_file>";
-int cmd_main(int argc, const char **argv)
+int cmd__delta(int argc, const char **argv)
{
int fd;
struct stat st;
+#include "test-tool.h"
#include "git-compat-util.h"
#if defined(GIT_WINDOWS_NATIVE)
#endif
-int cmd_main(int argc, const char **argv)
+int cmd__drop_caches(int argc, const char **argv)
{
cmd_sync();
return cmd_dropcaches();
+#include "test-tool.h"
#include "cache.h"
#include "tree.h"
#include "cache-tree.h"
return errs;
}
-int cmd_main(int ac, const char **av)
+int cmd__dump_cache_tree(int ac, const char **av)
{
struct index_state istate;
struct cache_tree *another = cache_tree();
+#include "test-tool.h"
#include "cache.h"
#include "split-index.h"
#include "ewah/ewok.h"
printf(" %d", (int)pos);
}
-int cmd_main(int ac, const char **av)
+int cmd__dump_split_index(int ac, const char **av)
{
struct split_index *si;
int i;
+#include "test-tool.h"
#include "cache.h"
#include "object.h"
#include "decorate.h"
-int cmd_main(int argc, const char **argv)
+int cmd__example_decorate(int argc, const char **argv)
{
struct decoration n;
struct object_id one_oid = { {1} };
* Copyright (C) 2007 by Nicolas Pitre, licensed under the GPL version 2.
*/
+#include "test-tool.h"
#include "git-compat-util.h"
-int cmd_main(int argc, const char **argv)
+int cmd__genrandom(int argc, const char **argv)
{
unsigned long count, next = 0;
unsigned char *c;
+#include "test-tool.h"
#include "git-compat-util.h"
#include "hashmap.h"
#include "strbuf.h"
/*
* Test performance of hashmap.[ch]
- * Usage: time echo "perfhashmap method rounds" | test-hashmap
+ * Usage: time echo "perfhashmap method rounds" | test-tool hashmap
*/
static void perf_hashmap(unsigned int method, unsigned int rounds)
{
*
* perfhashmap method rounds -> test hashmap.[ch] performance
*/
-int cmd_main(int argc, const char **argv)
+int cmd__hashmap(int argc, const char **argv)
{
struct strbuf line = STRBUF_INIT;
struct hashmap map;
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__index_version(int argc, const char **argv)
{
struct cache_header hdr;
int version;
+#include "test-tool.h"
#include "cache.h"
#include "parse-options.h"
}
}
-int cmd_main(int argc, const char **argv)
+int cmd__lazy_init_name_hash(int argc, const char **argv)
{
const char *usage[] = {
- "test-lazy-init-name-hash -d (-s | -m)",
- "test-lazy-init-name-hash -p [-c c]",
- "test-lazy-init-name-hash -a a [--step s] [-c c]",
- "test-lazy-init-name-hash (-s | -m) [-c c]",
- "test-lazy-init-name-hash -s -m [-c c]",
+ "test-tool lazy-init-name-hash -d (-s | -m)",
+ "test-tool lazy-init-name-hash -p [-c c]",
+ "test-tool lazy-init-name-hash -a a [--step s] [-c c]",
+ "test-tool lazy-init-name-hash (-s | -m) [-c c]",
+ "test-tool lazy-init-name-hash -s -m [-c c]",
NULL
};
struct option options[] = {
+#include "test-tool.h"
#include "cache.h"
#include "tree.h"
-int cmd_main(int ac, const char **av)
+int cmd__match_trees(int ac, const char **av)
{
struct object_id hash1, hash2, shifted;
struct tree *one, *two;
+#include "test-tool.h"
#include "cache.h"
#include "mergesort.h"
return strcmp(x->text, y->text);
}
-int cmd_main(int argc, const char **argv)
+int cmd__mergesort(int argc, const char **argv)
{
struct line *line, *p = NULL, *lines = NULL;
struct strbuf sb = STRBUF_INIT;
/*
* test-mktemp.c: code to exercise the creation of temporary files
*/
+#include "test-tool.h"
#include "git-compat-util.h"
-int cmd_main(int argc, const char **argv)
+int cmd__mktemp(int argc, const char **argv)
{
if (argc != 2)
usage("Expected 1 parameter defining the temporary file template");
+#include "test-tool.h"
#include "git-compat-util.h"
#include "thread-utils.h"
-int cmd_main(int argc, const char **argv)
+int cmd__online_cpus(int argc, const char **argv)
{
printf("%d\n", online_cpus());
return 0;
+#include "test-tool.h"
#include "cache.h"
#include "string-list.h"
{ NULL, NULL }
};
-int cmd_main(int argc, const char **argv)
+int cmd__path_utils(int argc, const char **argv)
{
if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
char *buf = xmallocz(strlen(argv[2]));
+#include "test-tool.h"
#include "cache.h"
#include "prio-queue.h"
free(v);
}
-int cmd_main(int argc, const char **argv)
+int cmd__prio_queue(int argc, const char **argv)
{
struct prio_queue pq = { intcmp };
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__read_cache(int argc, const char **argv)
{
int i, cnt = 1;
if (argc == 2)
+#include "test-tool.h"
#include "cache.h"
#include "refs.h"
#include "worktree.h"
+#include "object-store.h"
static const char *notnull(const char *arg, const char *name)
{
{ NULL, NULL }
};
-int cmd_main(int argc, const char **argv)
+int cmd__ref_store(int argc, const char **argv)
{
struct ref_store *refs;
const char *func;
+#include "test-tool.h"
#include "git-compat-util.h"
#include "gettext.h"
return 0;
}
-int cmd_main(int argc, const char **argv)
+int cmd__regex(int argc, const char **argv)
{
const char *pat;
const char *str;
if (argc == 2 && !strcmp(argv[1], "--bug"))
return test_regex_bug();
else if (argc < 3)
- usage("test-regex --bug\n"
- "test-regex <pattern> <string> [<options>]");
+ usage("test-tool regex --bug\n"
+ "test-tool regex <pattern> <string> [<options>]");
argv++;
pat = *argv++;
* published by the Free Software Foundation.
*/
+#include "test-tool.h"
#include "cache.h"
#include "commit.h"
#include "diff.h"
return got_revision;
}
-int cmd_main(int argc, const char **argv)
+int cmd__revision_walking(int argc, const char **argv)
{
if (argc < 2)
return 1;
* published by the Free Software Foundation.
*/
+#include "test-tool.h"
#include "git-compat-util.h"
#include "run-command.h"
#include "argv-array.h"
return 1;
}
-int cmd_main(int argc, const char **argv)
+int cmd__run_command(int argc, const char **argv)
{
struct child_process proc = CHILD_PROCESS_INIT;
int jobs;
+#include "test-tool.h"
#include "cache.h"
#include "lockfile.h"
#include "tree.h"
static struct lock_file index_lock;
-int cmd_main(int ac, const char **av)
+int cmd__scrap_cache_tree(int ac, const char **av)
{
setup_git_directory();
hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
+#include "test-tool.h"
#include "cache.h"
#include "sha1-array.h"
return 0;
}
-int cmd_main(int argc, const char **argv)
+int cmd__sha1_array(int argc, const char **argv)
{
struct oid_array array = OID_ARRAY_INIT;
struct strbuf line = STRBUF_INIT;
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int ac, const char **av)
+int cmd__sha1(int ac, const char **av)
{
git_SHA_CTX ctx;
unsigned char sha1[20];
#!/bin/sh
dd if=/dev/zero bs=1048576 count=100 2>/dev/null |
-/usr/bin/time t/helper/test-sha1 >/dev/null
+/usr/bin/time t/helper/test-tool sha1 >/dev/null
while read expect cnt pfx
do
test -z "$pfx" || echo "$pfx"
dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null |
perl -pe 'y/\000/g/'
- } | ./t/helper/test-sha1 $cnt
+ } | ./t/helper/test-tool sha1 $cnt
)
if test "$expect" = "$actual"
then
+#include "test-tool.h"
#include "cache.h"
#include "sigchain.h"
X(three)
#undef X
-int cmd_main(int argc, const char **argv) {
+int cmd__sigchain(int argc, const char **argv) {
sigchain_push(SIGTERM, one);
sigchain_push(SIGTERM, two);
sigchain_push(SIGTERM, three);
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__strcmp_offset(int argc, const char **argv)
{
int result;
size_t offset;
+#include "test-tool.h"
#include "cache.h"
#include "string-list.h"
return starts_with(item->string, prefix);
}
-int cmd_main(int argc, const char **argv)
+int cmd__string_list(int argc, const char **argv)
{
if (argc == 5 && !strcmp(argv[1], "split")) {
struct string_list list = STRING_LIST_INIT_DUP;
+#include "test-tool.h"
#include "cache.h"
#include "config.h"
#include "submodule-config.h"
exit(1);
}
-int cmd_main(int argc, const char **argv)
+int cmd__submodule_config(int argc, const char **argv)
{
const char **arg = argv;
int my_argc = argc;
+#include "test-tool.h"
#include "cache.h"
#include "run-command.h"
-int cmd_main(int argc, const char **argv)
+int cmd__subprocess(int argc, const char **argv)
{
struct child_process cp = CHILD_PROCESS_INIT;
int nogit = 0;
--- /dev/null
+#include "git-compat-util.h"
+#include "test-tool.h"
+
+struct test_cmd {
+ const char *name;
+ int (*fn)(int argc, const char **argv);
+};
+
+static struct test_cmd cmds[] = {
+ { "chmtime", cmd__chmtime },
+ { "config", cmd__config },
+ { "ctype", cmd__ctype },
+ { "date", cmd__date },
+ { "delta", cmd__delta },
+ { "drop-caches", cmd__drop_caches },
+ { "dump-cache-tree", cmd__dump_cache_tree },
+ { "dump-split-index", cmd__dump_split_index },
+ { "example-decorate", cmd__example_decorate },
+ { "genrandom", cmd__genrandom },
+ { "hashmap", cmd__hashmap },
+ { "index-version", cmd__index_version },
+ { "lazy-init-name-hash", cmd__lazy_init_name_hash },
+ { "match-trees", cmd__match_trees },
+ { "mergesort", cmd__mergesort },
+ { "mktemp", cmd__mktemp },
+ { "online-cpus", cmd__online_cpus },
+ { "path-utils", cmd__path_utils },
+ { "prio-queue", cmd__prio_queue },
+ { "read-cache", cmd__read_cache },
+ { "ref-store", cmd__ref_store },
+ { "regex", cmd__regex },
+ { "revision-walking", cmd__revision_walking },
+ { "run-command", cmd__run_command },
+ { "scrap-cache-tree", cmd__scrap_cache_tree },
+ { "sha1-array", cmd__sha1_array },
+ { "sha1", cmd__sha1 },
+ { "sigchain", cmd__sigchain },
+ { "strcmp-offset", cmd__strcmp_offset },
+ { "string-list", cmd__string_list },
+ { "submodule-config", cmd__submodule_config },
+ { "subprocess", cmd__subprocess },
+ { "urlmatch-normalization", cmd__urlmatch_normalization },
+ { "wildmatch", cmd__wildmatch },
+ { "write-cache", cmd__write_cache },
+};
+
+int cmd_main(int argc, const char **argv)
+{
+ int i;
+
+ if (argc < 2)
+ die("I need a test name!");
+
+ for (i = 0; i < ARRAY_SIZE(cmds); i++) {
+ if (!strcmp(cmds[i].name, argv[1])) {
+ argv++;
+ argc--;
+ return cmds[i].fn(argc, argv);
+ }
+ }
+ die("There is no test named '%s'", argv[1]);
+}
--- /dev/null
+#ifndef __TEST_TOOL_H__
+#define __TEST_TOOL_H__
+
+int cmd__chmtime(int argc, const char **argv);
+int cmd__config(int argc, const char **argv);
+int cmd__ctype(int argc, const char **argv);
+int cmd__date(int argc, const char **argv);
+int cmd__delta(int argc, const char **argv);
+int cmd__drop_caches(int argc, const char **argv);
+int cmd__dump_cache_tree(int argc, const char **argv);
+int cmd__dump_split_index(int argc, const char **argv);
+int cmd__example_decorate(int argc, const char **argv);
+int cmd__genrandom(int argc, const char **argv);
+int cmd__hashmap(int argc, const char **argv);
+int cmd__index_version(int argc, const char **argv);
+int cmd__lazy_init_name_hash(int argc, const char **argv);
+int cmd__match_trees(int argc, const char **argv);
+int cmd__mergesort(int argc, const char **argv);
+int cmd__mktemp(int argc, const char **argv);
+int cmd__online_cpus(int argc, const char **argv);
+int cmd__path_utils(int argc, const char **argv);
+int cmd__prio_queue(int argc, const char **argv);
+int cmd__read_cache(int argc, const char **argv);
+int cmd__ref_store(int argc, const char **argv);
+int cmd__regex(int argc, const char **argv);
+int cmd__revision_walking(int argc, const char **argv);
+int cmd__run_command(int argc, const char **argv);
+int cmd__scrap_cache_tree(int argc, const char **argv);
+int cmd__sha1_array(int argc, const char **argv);
+int cmd__sha1(int argc, const char **argv);
+int cmd__sigchain(int argc, const char **argv);
+int cmd__strcmp_offset(int argc, const char **argv);
+int cmd__string_list(int argc, const char **argv);
+int cmd__submodule_config(int argc, const char **argv);
+int cmd__subprocess(int argc, const char **argv);
+int cmd__urlmatch_normalization(int argc, const char **argv);
+int cmd__wildmatch(int argc, const char **argv);
+int cmd__write_cache(int argc, const char **argv);
+
+#endif
+#include "test-tool.h"
#include "git-compat-util.h"
#include "urlmatch.h"
-int cmd_main(int argc, const char **argv)
+int cmd__urlmatch_normalization(int argc, const char **argv)
{
- const char usage[] = "test-urlmatch-normalization [-p | -l] <url1> | <url1> <url2>";
+ const char usage[] = "test-tool urlmatch-normalization [-p | -l] <url1> | <url1> <url2>";
char *url1, *url2;
int opt_p = 0, opt_l = 0;
+#include "test-tool.h"
#include "cache.h"
-int cmd_main(int argc, const char **argv)
+int cmd__wildmatch(int argc, const char **argv)
{
int i;
for (i = 2; i < argc; i++) {
+#include "test-tool.h"
#include "cache.h"
#include "lockfile.h"
static struct lock_file index_lock;
-int cmd_main(int argc, const char **argv)
+int cmd__write_cache(int argc, const char **argv)
{
int i, cnt = 1, lockfd;
if (argc == 2)
then
path=$(cygpath --windows "$path")
else
- path=$(test-path-utils real_path "$path")
+ path=$(test-tool path-utils real_path "$path")
fi &&
echo "$path"
}
svnrepo="file://$svnrepo"
poke() {
- test-chmtime +1 "$1"
+ test-tool chmtime +1 "$1"
}
# We need this, because we should pass empty configuration directory to
# Compute and append pack trailer to "$1"
pack_trailer () {
- test-sha1 -b <"$1" >trailer.tmp &&
+ test-tool sha1 -b <"$1" >trailer.tmp &&
cat trailer.tmp >>"$1" &&
rm -f trailer.tmp
}
}
my (@dirs, %dirnames, %dirabbrevs, %prefixes, @tests,
- $codespeed, $subsection, $reponame);
+ $codespeed, $sortby, $subsection, $reponame);
while (scalar @ARGV) {
my $arg = $ARGV[0];
my $dir;
shift @ARGV;
next;
}
+ if ($arg =~ /--sort-by(?:=(.*))?/) {
+ shift @ARGV;
+ if (defined $1) {
+ $sortby = $1;
+ } else {
+ $sortby = shift @ARGV;
+ if (! defined $sortby) {
+ die "'--sort-by' requires an argument";
+ }
+ }
+ next;
+ }
if ($arg eq "--subsection") {
shift @ARGV;
$subsection = $ARGV[0];
return 0;
}
+sub display_dir {
+ my ($d) = @_;
+ return exists $dirabbrevs{$d} ? $dirabbrevs{$d} : $dirnames{$d};
+}
+
sub print_default_results {
my %descrs;
my $descrlen = 4; # "Test"
my %times;
my @colwidth = ((0)x@dirs);
for my $i (0..$#dirs) {
- my $d = $dirs[$i];
- my $w = length (exists $dirabbrevs{$d} ? $dirabbrevs{$d} : $dirnames{$d});
+ my $w = length display_dir($dirs[$i]);
$colwidth[$i] = $w if $w > $colwidth[$i];
}
for my $t (@subtests) {
printf "%-${descrlen}s", "Test";
for my $i (0..$#dirs) {
- my $d = $dirs[$i];
- printf " %-$colwidth[$i]s", (exists $dirabbrevs{$d} ? $dirabbrevs{$d} : $dirnames{$d});
+ printf " %-$colwidth[$i]s", display_dir($dirs[$i]);
}
print "\n";
print "-"x$totalwidth, "\n";
}
}
+sub print_sorted_results {
+ my ($sortby) = @_;
+
+ if ($sortby ne "regression") {
+ die "only 'regression' is supported as '--sort-by' argument";
+ }
+
+ my @evolutions;
+ for my $t (@subtests) {
+ my ($prevr, $prevu, $prevs, $prevrev);
+ for my $i (0..$#dirs) {
+ my $d = $dirs[$i];
+ my ($r, $u, $s) = get_times("$resultsdir/$prefixes{$d}$t.times");
+ if ($i > 0 and defined $r and defined $prevr and $prevr > 0) {
+ my $percent = 100.0 * ($r - $prevr) / $prevr;
+ push @evolutions, { "percent" => $percent,
+ "test" => $t,
+ "prevrev" => $prevrev,
+ "rev" => $d,
+ "prevr" => $prevr,
+ "r" => $r,
+ "prevu" => $prevu,
+ "u" => $u,
+ "prevs" => $prevs,
+ "s" => $s};
+ }
+ ($prevr, $prevu, $prevs, $prevrev) = ($r, $u, $s, $d);
+ }
+ }
+
+ my @sorted_evolutions = sort { $b->{percent} <=> $a->{percent} } @evolutions;
+
+ for my $e (@sorted_evolutions) {
+ printf "%+.1f%%", $e->{percent};
+ print " " . $e->{test};
+ print " " . format_times($e->{prevr}, $e->{prevu}, $e->{prevs});
+ print " " . format_times($e->{r}, $e->{u}, $e->{s});
+ print " " . display_dir($e->{prevrev});
+ print " " . display_dir($e->{rev});
+ print "\n";
+ }
+}
+
sub print_codespeed_results {
my ($subsection) = @_;
if ($codespeed) {
print_codespeed_results($subsection);
+} elsif (defined $sortby) {
+ print_sorted_results($sortby);
} else {
print_default_results();
}
count=1000
test_perf "read_cache/discard_cache $count times" "
- test-read-cache $count
+ test-tool read-cache $count
"
test_done
test_checkout_worktree
test_expect_success 'verify both methods build the same hashmaps' '
- test-lazy-init-name-hash --dump --single >out.single &&
- if test-lazy-init-name-hash --dump --multi >out.multi
+ test-tool lazy-init-name-hash --dump --single >out.single &&
+ if test-tool lazy-init-name-hash --dump --multi >out.multi
then
test_set_prereq REPO_BIG_ENOUGH_FOR_MULTI &&
sort <out.single >sorted.single &&
'
test_perf "single-threaded, $desc" "
- test-lazy-init-name-hash --single --count=$count
+ test-tool lazy-init-name-hash --single --count=$count
"
test_perf REPO_BIG_ENOUGH_FOR_MULTI "multi-threaded, $desc" "
- test-lazy-init-name-hash --multi --count=$count
+ test-tool lazy-init-name-hash --multi --count=$count
"
test_done
count=3
test_perf "write_locked_index $count times ($nr_files files)" "
- test-write-cache $count
+ test-tool write-cache $count
"
test_done
'
test_perf 'string_list_sort()' '
- test-string-list sort <unsorted >actual
+ test-tool string-list sort <unsorted >actual
'
test_expect_success 'string_list_sort() sorts like sort(1)' '
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
- test-drop-caches
+ test-tool drop-caches
fi
test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
- test-drop-caches
+ test-tool drop-caches
fi
test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
- test-drop-caches
+ test-tool drop-caches
fi
test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
- test-drop-caches
+ test-tool drop-caches
fi
test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
- test-drop-caches
+ test-tool drop-caches
fi
test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
- test-drop-caches
+ test-tool drop-caches
fi
test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
EOF
test_expect_success 'sigchain works' '
- { test-sigchain >actual; ret=$?; } &&
+ { test-tool sigchain >actual; ret=$?; } &&
{
# Signal death by raise() on Windows acts like exit(3),
# regardless of the signal number. So we must allow that
test_expect_success !MINGW 'signals are propagated using shell convention' '
# we use exec here to avoid any sub-shell interpretation
# of the exit code
- git config alias.sigterm "!exec test-sigchain" &&
+ git config alias.sigterm "!exec test-tool sigchain" &&
test_expect_code 143 git sigterm
'
}
test_expect_success 'create blob' '
- test-genrandom foo 16384 >file &&
+ test-tool genrandom foo 16384 >file &&
git add file
'
t=$(($TEST_DATE_NOW - $1))
echo "$t -> $2" >expect
test_expect_${3:-success} "relative date ($2)" "
- test-date relative $t >actual &&
+ test-tool date relative $t >actual &&
test_i18ncmp expect actual
"
}
zone=$5
test_expect_success $prereqs "show date ($format:$time)" '
echo "$time -> $expect" >expect &&
- TZ=${zone:-$TZ} test-date show:"$format" "$time" >actual &&
+ TZ=${zone:-$TZ} test-tool date show:"$format" "$time" >actual &&
test_cmp expect actual
'
}
check_parse() {
echo "$1 -> $2" >expect
test_expect_${4:-success} "parse date ($1${3:+ TZ=$3})" "
- TZ=${3:-$TZ} test-date parse '$1' >actual &&
+ TZ=${3:-$TZ} test-tool date parse '$1' >actual &&
test_cmp expect actual
"
}
check_approxidate() {
echo "$1 -> $2 +0000" >expect
test_expect_${3:-success} "parse approxidate ($1)" "
- test-date approxidate '$1' >actual &&
+ test-tool date approxidate '$1' >actual &&
test_cmp expect actual
"
}
10
EOF
test_expect_success 'basic ordering' '
- test-prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&
+ test-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&
test_cmp expect actual
'
6
EOF
test_expect_success 'mixed put and get' '
- test-prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&
+ test-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&
test_cmp expect actual
'
NULL
EOF
test_expect_success 'notice empty queue' '
- test-prio-queue 1 2 get get get 1 2 get get get >actual &&
+ test-tool prio-queue 1 2 get get get 1 2 get get get >actual &&
test_cmp expect actual
'
. ./test-lib.sh
test_hashmap() {
- echo "$1" | test-hashmap $3 > actual &&
+ echo "$1" | test-tool hashmap $3 > actual &&
echo "$2" > expect &&
test_cmp expect actual
}
echo value40 >> expect &&
echo size >> in &&
echo 64 39 >> expect &&
- cat in | test-hashmap > out &&
+ cat in | test-tool hashmap > out &&
test_cmp expect out
'
fi
test_expect_success 'test-sha1 detects shattered pdf' '
- test_must_fail test-sha1 <"$TEST_DATA/shattered-1.pdf" 2>err &&
+ test_must_fail test-tool sha1 <"$TEST_DATA/shattered-1.pdf" 2>err &&
test_i18ngrep collision err &&
grep 38762cf7f55934b34d179ae6a4c80cadccbb7f0a err
'
generate_random_characters () {
LEN=$1
NAME=$2
- test-genrandom some-seed $LEN |
+ test-tool genrandom some-seed $LEN |
perl -pe "s/./chr((ord($&) % 26) + ord('a'))/sge" >"$TEST_ROOT/$NAME"
}
'
test_expect_success 'filter that does not read is fine' '
- test-genrandom foo $((128 * 1024 + 1)) >big &&
+ test-tool genrandom foo $((128 * 1024 + 1)) >big &&
echo "big filter=epipe" >.gitattributes &&
test_config filter.epipe.clean "echo xyzzy" &&
git add big &&
test_expect_success 'OPT_CALLBACK() and callback errors work' '
test_must_fail test-parse-options --no-length >output 2>output.err &&
test_i18ncmp expect output &&
- test_i18ncmp expect.err output.err
+ test_must_be_empty output.err
'
cat >expect <<\EOF
--- /dev/null
+#!/bin/sh
+
+test_description='Test commands behavior when given invalid argument value'
+
+. ./test-lib.sh
+
+test_expect_success 'setup ' '
+ test_commit "v1.0"
+'
+
+test_expect_success 'tag --contains <existent_tag>' '
+ git tag --contains "v1.0" >actual 2>actual.err &&
+ grep "v1.0" actual &&
+ test_line_count = 0 actual.err
+'
+
+test_expect_success 'tag --contains <inexistent_tag>' '
+ test_must_fail git tag --contains "notag" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "error" actual.err &&
+ test_i18ngrep ! "usage" actual.err
+'
+
+test_expect_success 'tag --no-contains <existent_tag>' '
+ git tag --no-contains "v1.0" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_line_count = 0 actual.err
+'
+
+test_expect_success 'tag --no-contains <inexistent_tag>' '
+ test_must_fail git tag --no-contains "notag" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "error" actual.err &&
+ test_i18ngrep ! "usage" actual.err
+'
+
+test_expect_success 'tag usage error' '
+ test_must_fail git tag --noopt >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "usage" actual.err
+'
+
+test_expect_success 'branch --contains <existent_commit>' '
+ git branch --contains "master" >actual 2>actual.err &&
+ test_i18ngrep "master" actual &&
+ test_line_count = 0 actual.err
+'
+
+test_expect_success 'branch --contains <inexistent_commit>' '
+ test_must_fail git branch --no-contains "nocommit" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "error" actual.err &&
+ test_i18ngrep ! "usage" actual.err
+'
+
+test_expect_success 'branch --no-contains <existent_commit>' '
+ git branch --no-contains "master" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_line_count = 0 actual.err
+'
+
+test_expect_success 'branch --no-contains <inexistent_commit>' '
+ test_must_fail git branch --no-contains "nocommit" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "error" actual.err &&
+ test_i18ngrep ! "usage" actual.err
+'
+
+test_expect_success 'branch usage error' '
+ test_must_fail git branch --noopt >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "usage" actual.err
+'
+
+test_expect_success 'for-each-ref --contains <existent_object>' '
+ git for-each-ref --contains "master" >actual 2>actual.err &&
+ test_line_count = 2 actual &&
+ test_line_count = 0 actual.err
+'
+
+test_expect_success 'for-each-ref --contains <inexistent_object>' '
+ test_must_fail git for-each-ref --no-contains "noobject" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "error" actual.err &&
+ test_i18ngrep ! "usage" actual.err
+'
+
+test_expect_success 'for-each-ref --no-contains <existent_object>' '
+ git for-each-ref --no-contains "master" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_line_count = 0 actual.err
+'
+
+test_expect_success 'for-each-ref --no-contains <inexistent_object>' '
+ test_must_fail git for-each-ref --no-contains "noobject" >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "error" actual.err &&
+ test_i18ngrep ! "usage" actual.err
+'
+
+test_expect_success 'for-each-ref usage error' '
+ test_must_fail git for-each-ref --noopt >actual 2>actual.err &&
+ test_line_count = 0 actual &&
+ test_i18ngrep "usage" actual.err
+'
+
+test_done
. ./test-lib.sh
norm_path() {
- expected=$(test-path-utils print_path "$2")
+ expected=$(test-tool path-utils print_path "$2")
test_expect_success $3 "normalize path: $1 => $2" \
- "test \"\$(test-path-utils normalize_path_copy '$1')\" = '$expected'"
+ "test \"\$(test-tool path-utils normalize_path_copy '$1')\" = '$expected'"
}
relative_path() {
- expected=$(test-path-utils print_path "$3")
+ expected=$(test-tool path-utils print_path "$3")
test_expect_success $4 "relative path: $1 $2 => $3" \
- "test \"\$(test-path-utils relative_path '$1' '$2')\" = '$expected'"
+ "test \"\$(test-tool path-utils relative_path '$1' '$2')\" = '$expected'"
}
test_submodule_relative_url() {
# On Windows, we are using MSYS's bash, which mangles the paths.
# Absolute paths are anchored at the MSYS installation directory,
# which means that the path / accounts for this many characters:
-rootoff=$(test-path-utils normalize_path_copy / | wc -c)
+rootoff=$(test-tool path-utils normalize_path_copy / | wc -c)
# Account for the trailing LF:
if test $rootoff = 2; then
rootoff= # we are on Unix
# In MSYS2, the root directory "/" is translated into a Windows
# directory *with* trailing slash. Let's test for that and adjust
# our expected longest ancestor length accordingly.
- case "$(test-path-utils print_path /)" in
+ case "$(test-tool path-utils print_path /)" in
*/) rootslash=1;;
*) rootslash=0;;
esac
expected=$(($expected+$rootoff))
fi
test_expect_success "longest ancestor: $1 $2 => $expected" \
- "actual=\$(test-path-utils longest_ancestor_length '$1' '$2') &&
+ "actual=\$(test-tool path-utils longest_ancestor_length '$1' '$2') &&
test \"\$actual\" = '$expected'"
}
;;
esac
-test_expect_success basename 'test-path-utils basename'
-test_expect_success dirname 'test-path-utils dirname'
+test_expect_success basename 'test-tool path-utils basename'
+test_expect_success dirname 'test-tool path-utils dirname'
norm_path "" ""
norm_path . ""
ancestor /foo/bar /bar -1
test_expect_success 'strip_path_suffix' '
- test c:/msysgit = $(test-path-utils strip_path_suffix \
+ test c:/msysgit = $(test-tool path-utils strip_path_suffix \
c:/msysgit/libexec//git-core libexec/git-core)
'
test_expect_success 'absolute path rejects the empty string' '
- test_must_fail test-path-utils absolute_path ""
+ test_must_fail test-tool path-utils absolute_path ""
'
test_expect_success 'real path rejects the empty string' '
- test_must_fail test-path-utils real_path ""
+ test_must_fail test-tool path-utils real_path ""
'
test_expect_success POSIX 'real path works on absolute paths 1' '
nopath="hopefully-absent-path" &&
- test "/" = "$(test-path-utils real_path "/")" &&
- test "/$nopath" = "$(test-path-utils real_path "/$nopath")"
+ test "/" = "$(test-tool path-utils real_path "/")" &&
+ test "/$nopath" = "$(test-tool path-utils real_path "/$nopath")"
'
test_expect_success 'real path works on absolute paths 2' '
nopath="hopefully-absent-path" &&
# Find an existing top-level directory for the remaining tests:
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
- test "$d" = "$(test-path-utils real_path "$d")" &&
- test "$d/$nopath" = "$(test-path-utils real_path "$d/$nopath")"
+ test "$d" = "$(test-tool path-utils real_path "$d")" &&
+ test "$d/$nopath" = "$(test-tool path-utils real_path "$d/$nopath")"
'
test_expect_success POSIX 'real path removes extra leading slashes' '
nopath="hopefully-absent-path" &&
- test "/" = "$(test-path-utils real_path "///")" &&
- test "/$nopath" = "$(test-path-utils real_path "///$nopath")" &&
+ test "/" = "$(test-tool path-utils real_path "///")" &&
+ test "/$nopath" = "$(test-tool path-utils real_path "///$nopath")" &&
# Find an existing top-level directory for the remaining tests:
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
- test "$d" = "$(test-path-utils real_path "//$d")" &&
- test "$d/$nopath" = "$(test-path-utils real_path "//$d/$nopath")"
+ test "$d" = "$(test-tool path-utils real_path "//$d")" &&
+ test "$d/$nopath" = "$(test-tool path-utils real_path "//$d/$nopath")"
'
test_expect_success 'real path removes other extra slashes' '
nopath="hopefully-absent-path" &&
# Find an existing top-level directory for the remaining tests:
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
- test "$d" = "$(test-path-utils real_path "$d///")" &&
- test "$d/$nopath" = "$(test-path-utils real_path "$d///$nopath")"
+ test "$d" = "$(test-tool path-utils real_path "$d///")" &&
+ test "$d/$nopath" = "$(test-tool path-utils real_path "$d///$nopath")"
'
test_expect_success SYMLINKS 'real path works on symlinks' '
mkdir third &&
dir="$(cd .git; pwd -P)" &&
dir2=third/../second/other/.git &&
- test "$dir" = "$(test-path-utils real_path $dir2)" &&
+ test "$dir" = "$(test-tool path-utils real_path $dir2)" &&
file="$dir"/index &&
- test "$file" = "$(test-path-utils real_path $dir2/index)" &&
+ test "$file" = "$(test-tool path-utils real_path $dir2/index)" &&
basename=blub &&
- test "$dir/$basename" = "$(cd .git && test-path-utils real_path "$basename")" &&
+ test "$dir/$basename" = "$(cd .git && test-tool path-utils real_path "$basename")" &&
ln -s ../first/file .git/syml &&
sym="$(cd first; pwd -P)"/file &&
- test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
+ test "$sym" = "$(test-tool path-utils real_path "$dir2/syml")"
'
test_expect_success SYMLINKS 'prefix_path works with absolute paths to work tree symlinks' '
ln -s target symlink &&
- test "$(test-path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink"
+ test "$(test-tool path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink"
'
test_expect_success 'prefix_path works with only absolute path to work tree' '
echo "" >expected &&
- test-path-utils prefix_path prefix "$(pwd)" >actual &&
+ test-tool path-utils prefix_path prefix "$(pwd)" >actual &&
test_cmp expected actual
'
test_expect_success 'prefix_path rejects absolute path to dir with same beginning as work tree' '
- test_must_fail test-path-utils prefix_path prefix "$(pwd)a"
+ test_must_fail test-tool path-utils prefix_path prefix "$(pwd)a"
'
test_expect_success SYMLINKS 'prefix_path works with absolute path to a symlink to work tree having same beginning as work tree' '
git init repo &&
ln -s repo repolink &&
- test "a" = "$(cd repo && test-path-utils prefix_path prefix "$(pwd)/../repolink/a")"
+ test "a" = "$(cd repo && test-tool path-utils prefix_path prefix "$(pwd)/../repolink/a")"
'
relative_path /foo/a/b/c/ /foo/a/b/ c/
>empty
test_expect_success 'start_command reports ENOENT' '
- test-run-command start-command-ENOENT ./does-not-exist
+ test-tool run-command start-command-ENOENT ./does-not-exist
'
test_expect_success 'run_command can run a command' '
cat hello-script >hello.sh &&
chmod +x hello.sh &&
- test-run-command run-command ./hello.sh >actual 2>err &&
+ test-tool run-command run-command ./hello.sh >actual 2>err &&
test_cmp hello-script actual &&
test_cmp empty err
cat hello-script
EOF
chmod +x hello &&
- test-run-command run-command ./hello >actual 2>err &&
+ test-tool run-command run-command ./hello >actual 2>err &&
test_cmp hello-script actual &&
test_cmp empty err
EOF
PATH=$PWD/bin1:$PWD/bin2:$PATH \
- test-run-command run-command greet >actual 2>err &&
+ test-tool run-command run-command greet >actual 2>err &&
test_cmp bin2/greet actual &&
test_cmp empty err
'
EOF
PATH=$PWD/bin1:$PWD/bin2:$PATH \
- test-run-command run-command greet >actual 2>err &&
+ test-tool run-command run-command greet >actual 2>err &&
test_cmp bin2/greet actual &&
test_cmp empty err
'
test_expect_success POSIXPERM 'run_command reports EACCES' '
cat hello-script >hello.sh &&
chmod -x hello.sh &&
- test_must_fail test-run-command run-command ./hello.sh 2>err &&
+ test_must_fail test-tool run-command run-command ./hello.sh 2>err &&
grep "fatal: cannot exec.*hello.sh" err
'
EOF
test_expect_success 'run_command runs in parallel with more jobs available than tasks' '
- test-run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
test_cmp expect actual
'
test_expect_success 'run_command runs in parallel with as many jobs as tasks' '
- test-run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
test_cmp expect actual
'
test_expect_success 'run_command runs in parallel with more tasks than jobs available' '
- test-run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
test_cmp expect actual
'
EOF
test_expect_success 'run_command is asked to abort gracefully' '
- test-run-command run-command-abort 3 false 2>actual &&
+ test-tool run-command run-command-abort 3 false 2>actual &&
test_cmp expect actual
'
EOF
test_expect_success 'run_command outputs ' '
- test-run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
test_cmp expect actual
'
test_trace () {
expect="$1"
shift
- GIT_TRACE=1 test-run-command "$@" run-command true 2>&1 >/dev/null | \
+ GIT_TRACE=1 test-tool run-command "$@" run-command true 2>&1 >/dev/null | \
sed 's/.* run_command: //' >actual &&
echo "$expect true" >expect &&
test_cmp expect actual
'
test_expect_success 'revision walking can be done twice' '
- test-revision-walking run-twice >run_twice_actual &&
+ test-tool revision-walking run-twice >run_twice_actual &&
test_cmp run_twice_expected run_twice_actual
'
test_split () {
cat >expected &&
test_expect_success "split $1 at $2, max $3" "
- test-string-list split '$1' '$2' '$3' >actual &&
+ test-tool string-list split '$1' '$2' '$3' >actual &&
test_cmp expected actual &&
- test-string-list split_in_place '$1' '$2' '$3' >actual &&
+ test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
test_cmp expected actual
"
}
EOF
test_expect_success "test filter_string_list" '
- test "x-" = "x$(test-string-list filter - y)" &&
- test "x-" = "x$(test-string-list filter no y)" &&
- test yes = "$(test-string-list filter yes y)" &&
- test yes = "$(test-string-list filter no:yes y)" &&
- test yes = "$(test-string-list filter yes:no y)" &&
- test y1:y2 = "$(test-string-list filter y1:y2 y)" &&
- test y2:y1 = "$(test-string-list filter y2:y1 y)" &&
- test "x-" = "x$(test-string-list filter x1:x2 y)"
+ test "x-" = "x$(test-tool string-list filter - y)" &&
+ test "x-" = "x$(test-tool string-list filter no y)" &&
+ test yes = "$(test-tool string-list filter yes y)" &&
+ test yes = "$(test-tool string-list filter no:yes y)" &&
+ test yes = "$(test-tool string-list filter yes:no y)" &&
+ test y1:y2 = "$(test-tool string-list filter y1:y2 y)" &&
+ test y2:y1 = "$(test-tool string-list filter y2:y1 y)" &&
+ test "x-" = "x$(test-tool string-list filter x1:x2 y)"
'
test_expect_success "test remove_duplicates" '
- test "x-" = "x$(test-string-list remove_duplicates -)" &&
- test "x" = "x$(test-string-list remove_duplicates "")" &&
- test a = "$(test-string-list remove_duplicates a)" &&
- test a = "$(test-string-list remove_duplicates a:a)" &&
- test a = "$(test-string-list remove_duplicates a:a:a:a:a)" &&
- test a:b = "$(test-string-list remove_duplicates a:b)" &&
- test a:b = "$(test-string-list remove_duplicates a:a:b)" &&
- test a:b = "$(test-string-list remove_duplicates a:b:b)" &&
- test a:b:c = "$(test-string-list remove_duplicates a:b:c)" &&
- test a:b:c = "$(test-string-list remove_duplicates a:a:b:c)" &&
- test a:b:c = "$(test-string-list remove_duplicates a:b:b:c)" &&
- test a:b:c = "$(test-string-list remove_duplicates a:b:c:c)" &&
- test a:b:c = "$(test-string-list remove_duplicates a:a:b:b:c:c)" &&
- test a:b:c = "$(test-string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
+ test "x-" = "x$(test-tool string-list remove_duplicates -)" &&
+ test "x" = "x$(test-tool string-list remove_duplicates "")" &&
+ test a = "$(test-tool string-list remove_duplicates a)" &&
+ test a = "$(test-tool string-list remove_duplicates a:a)" &&
+ test a = "$(test-tool string-list remove_duplicates a:a:a:a:a)" &&
+ test a:b = "$(test-tool string-list remove_duplicates a:b)" &&
+ test a:b = "$(test-tool string-list remove_duplicates a:a:b)" &&
+ test a:b = "$(test-tool string-list remove_duplicates a:b:b)" &&
+ test a:b:c = "$(test-tool string-list remove_duplicates a:b:c)" &&
+ test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:c)" &&
+ test a:b:c = "$(test-tool string-list remove_duplicates a:b:b:c)" &&
+ test a:b:c = "$(test-tool string-list remove_duplicates a:b:c:c)" &&
+ test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:b:c:c)" &&
+ test a:b:c = "$(test-tool string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
'
test_done
{
echo20 append 88 44 aa 55 &&
echo for_each_unique
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
test_cmp expect actual
'
echo20 append 88 44 aa 55 &&
echo20 append 88 44 aa 55 &&
echo for_each_unique
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
test_cmp expect actual
'
{
echo20 append 88 44 aa 55 &&
echo20 lookup 55
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
n=$(cat actual) &&
test "$n" -eq 1
'
{
echo20 append 88 44 aa 55 &&
echo20 lookup 33
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
n=$(cat actual) &&
test "$n" -lt 0
'
echo20 append 88 44 aa 55 &&
echo20 append 88 44 aa 55 &&
echo20 lookup 55
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
n=$(cat actual) &&
test "$n" -ge 2 &&
test "$n" -le 3
echo20 append 88 44 aa 55 &&
echo20 append 88 44 aa 55 &&
echo20 lookup 66
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
n=$(cat actual) &&
test "$n" -lt 0
'
echo "append 5555555555555555555555555555555555555555" &&
echo "append 555555555555555555555555555555555555555f" &&
echo20 lookup 55
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
n=$(cat actual) &&
test "$n" -eq 0
'
{
echo20 append 55 55 &&
echo20 lookup 55
- } | test-sha1-array >actual &&
+ } | test-tool sha1-array >actual &&
n=$(cat actual) &&
test "$n" -ge 0 &&
test "$n" -le 1
do
test_expect_success "strcmp_offset($s1, $s2)" '
echo "$expect" >expect &&
- test-strcmp-offset "$s1" "$s2" >actual &&
+ test-tool strcmp-offset "$s1" "$s2" >actual &&
test_cmp expect actual
'
done <<-EOF
. ./test-lib.sh
test_expect_success 'character classes (isspace, isalpha etc.)' '
- test-ctype
+ test-tool ctype
'
test_expect_success 'mktemp to nonexistent directory prints filename' '
- test_must_fail test-mktemp doesnotexist/testXXXXXX 2>err &&
+ test_must_fail test-tool mktemp doesnotexist/testXXXXXX 2>err &&
grep "doesnotexist/test" err
'
mkdir cannotwrite &&
chmod -w cannotwrite &&
test_when_finished "chmod +w cannotwrite" &&
- test_must_fail test-mktemp cannotwrite/testXXXXXX 2>err &&
+ test_must_fail test-tool mktemp cannotwrite/testXXXXXX 2>err &&
grep "cannotwrite/test" err
'
test_expect_success 'check for a bug in the regex routines' '
# if this test fails, re-build git with NO_REGEX=1
- test-regex --bug
+ test-tool regex --bug
'
test_done
. ./test-lib.sh
cmp_cache_tree () {
- test-dump-cache-tree | sed -e '/#(ref)/d' >actual &&
+ test-tool dump-cache-tree | sed -e '/#(ref)/d' >actual &&
sed "s/$_x40/SHA/" <actual >filtered &&
test_cmp "$1" filtered
}
# We don't bother with actually checking the SHA1:
-# test-dump-cache-tree already verifies that all existing data is
+# test-tool dump-cache-tree already verifies that all existing data is
# correct.
generate_expected_cache_tree_rec () {
dir="$1${1:+/}" &&
test_invalid_cache_tree () {
printf "invalid %s ()\n" "" "$@" >expect &&
- test-dump-cache-tree |
+ test-tool dump-cache-tree |
sed -n -e "s/[0-9]* subtrees//" -e '/#(ref)/d' -e '/^invalid /p' >actual &&
test_cmp expect actual
}
'
test_expect_success 'write-tree establishes cache-tree' '
- test-scrap-cache-tree &&
+ test-tool scrap-cache-tree &&
git write-tree &&
test_cache_tree
'
-test_expect_success 'test-scrap-cache-tree works' '
+test_expect_success 'test-tool scrap-cache-tree works' '
git read-tree HEAD &&
- test-scrap-cache-tree &&
+ test-tool scrap-cache-tree &&
test_no_cache_tree
'
'
test_expect_success 'reset --hard gives cache-tree' '
- test-scrap-cache-tree &&
+ test-tool scrap-cache-tree &&
git reset --hard &&
test_cache_tree
'
git update-index --split-index &&
>split &&
git add split &&
- test-dump-split-index .git/index | grep -v ^own >before &&
+ test-tool dump-split-index .git/index | grep -v ^own >before &&
git commit -m "as-is" &&
- test-dump-split-index .git/index | grep -v ^own >after &&
+ test-tool dump-split-index .git/index | grep -v ^own >after &&
test_cmp before after
'
# Note that only file: URLs should be allowed without a host
test_expect_success 'url scheme' '
- ! test-urlmatch-normalization "" &&
- ! test-urlmatch-normalization "_" &&
- ! test-urlmatch-normalization "scheme" &&
- ! test-urlmatch-normalization "scheme:" &&
- ! test-urlmatch-normalization "scheme:/" &&
- ! test-urlmatch-normalization "scheme://" &&
- ! test-urlmatch-normalization "file" &&
- ! test-urlmatch-normalization "file:" &&
- ! test-urlmatch-normalization "file:/" &&
- test-urlmatch-normalization "file://" &&
- ! test-urlmatch-normalization "://acme.co" &&
- ! test-urlmatch-normalization "x_test://acme.co" &&
- ! test-urlmatch-normalization "-test://acme.co" &&
- ! test-urlmatch-normalization "0test://acme.co" &&
- ! test-urlmatch-normalization "+test://acme.co" &&
- ! test-urlmatch-normalization ".test://acme.co" &&
- ! test-urlmatch-normalization "schem%6e://" &&
- test-urlmatch-normalization "x-Test+v1.0://acme.co" &&
- test "$(test-urlmatch-normalization -p "AbCdeF://x.Y")" = "abcdef://x.y/"
+ ! test-tool urlmatch-normalization "" &&
+ ! test-tool urlmatch-normalization "_" &&
+ ! test-tool urlmatch-normalization "scheme" &&
+ ! test-tool urlmatch-normalization "scheme:" &&
+ ! test-tool urlmatch-normalization "scheme:/" &&
+ ! test-tool urlmatch-normalization "scheme://" &&
+ ! test-tool urlmatch-normalization "file" &&
+ ! test-tool urlmatch-normalization "file:" &&
+ ! test-tool urlmatch-normalization "file:/" &&
+ test-tool urlmatch-normalization "file://" &&
+ ! test-tool urlmatch-normalization "://acme.co" &&
+ ! test-tool urlmatch-normalization "x_test://acme.co" &&
+ ! test-tool urlmatch-normalization "-test://acme.co" &&
+ ! test-tool urlmatch-normalization "0test://acme.co" &&
+ ! test-tool urlmatch-normalization "+test://acme.co" &&
+ ! test-tool urlmatch-normalization ".test://acme.co" &&
+ ! test-tool urlmatch-normalization "schem%6e://" &&
+ test-tool urlmatch-normalization "x-Test+v1.0://acme.co" &&
+ test "$(test-tool urlmatch-normalization -p "AbCdeF://x.Y")" = "abcdef://x.y/"
'
test_expect_success 'url authority' '
- ! test-urlmatch-normalization "scheme://user:pass@" &&
- ! test-urlmatch-normalization "scheme://?" &&
- ! test-urlmatch-normalization "scheme://#" &&
- ! test-urlmatch-normalization "scheme:///" &&
- ! test-urlmatch-normalization "scheme://:" &&
- ! test-urlmatch-normalization "scheme://:555" &&
- test-urlmatch-normalization "file://user:pass@" &&
- test-urlmatch-normalization "file://?" &&
- test-urlmatch-normalization "file://#" &&
- test-urlmatch-normalization "file:///" &&
- test-urlmatch-normalization "file://:" &&
- ! test-urlmatch-normalization "file://:555" &&
- test-urlmatch-normalization "scheme://user:pass@host" &&
- test-urlmatch-normalization "scheme://@host" &&
- test-urlmatch-normalization "scheme://%00@host" &&
- ! test-urlmatch-normalization "scheme://%%@host" &&
- ! test-urlmatch-normalization "scheme://host_" &&
- test-urlmatch-normalization "scheme://user:pass@host/" &&
- test-urlmatch-normalization "scheme://@host/" &&
- test-urlmatch-normalization "scheme://host/" &&
- test-urlmatch-normalization "scheme://host?x" &&
- test-urlmatch-normalization "scheme://host#x" &&
- test-urlmatch-normalization "scheme://host/@" &&
- test-urlmatch-normalization "scheme://host?@x" &&
- test-urlmatch-normalization "scheme://host#@x" &&
- test-urlmatch-normalization "scheme://[::1]" &&
- test-urlmatch-normalization "scheme://[::1]/" &&
- ! test-urlmatch-normalization "scheme://hos%41/" &&
- test-urlmatch-normalization "scheme://[invalid....:/" &&
- test-urlmatch-normalization "scheme://invalid....:]/" &&
- ! test-urlmatch-normalization "scheme://invalid....:[/" &&
- ! test-urlmatch-normalization "scheme://invalid....:["
+ ! test-tool urlmatch-normalization "scheme://user:pass@" &&
+ ! test-tool urlmatch-normalization "scheme://?" &&
+ ! test-tool urlmatch-normalization "scheme://#" &&
+ ! test-tool urlmatch-normalization "scheme:///" &&
+ ! test-tool urlmatch-normalization "scheme://:" &&
+ ! test-tool urlmatch-normalization "scheme://:555" &&
+ test-tool urlmatch-normalization "file://user:pass@" &&
+ test-tool urlmatch-normalization "file://?" &&
+ test-tool urlmatch-normalization "file://#" &&
+ test-tool urlmatch-normalization "file:///" &&
+ test-tool urlmatch-normalization "file://:" &&
+ ! test-tool urlmatch-normalization "file://:555" &&
+ test-tool urlmatch-normalization "scheme://user:pass@host" &&
+ test-tool urlmatch-normalization "scheme://@host" &&
+ test-tool urlmatch-normalization "scheme://%00@host" &&
+ ! test-tool urlmatch-normalization "scheme://%%@host" &&
+ ! test-tool urlmatch-normalization "scheme://host_" &&
+ test-tool urlmatch-normalization "scheme://user:pass@host/" &&
+ test-tool urlmatch-normalization "scheme://@host/" &&
+ test-tool urlmatch-normalization "scheme://host/" &&
+ test-tool urlmatch-normalization "scheme://host?x" &&
+ test-tool urlmatch-normalization "scheme://host#x" &&
+ test-tool urlmatch-normalization "scheme://host/@" &&
+ test-tool urlmatch-normalization "scheme://host?@x" &&
+ test-tool urlmatch-normalization "scheme://host#@x" &&
+ test-tool urlmatch-normalization "scheme://[::1]" &&
+ test-tool urlmatch-normalization "scheme://[::1]/" &&
+ ! test-tool urlmatch-normalization "scheme://hos%41/" &&
+ test-tool urlmatch-normalization "scheme://[invalid....:/" &&
+ test-tool urlmatch-normalization "scheme://invalid....:]/" &&
+ ! test-tool urlmatch-normalization "scheme://invalid....:[/" &&
+ ! test-tool urlmatch-normalization "scheme://invalid....:["
'
test_expect_success 'url port checks' '
- test-urlmatch-normalization "xyz://q@some.host:" &&
- test-urlmatch-normalization "xyz://q@some.host:456/" &&
- ! test-urlmatch-normalization "xyz://q@some.host:0" &&
- ! test-urlmatch-normalization "xyz://q@some.host:0000000" &&
- test-urlmatch-normalization "xyz://q@some.host:0000001?" &&
- test-urlmatch-normalization "xyz://q@some.host:065535#" &&
- test-urlmatch-normalization "xyz://q@some.host:65535" &&
- ! test-urlmatch-normalization "xyz://q@some.host:65536" &&
- ! test-urlmatch-normalization "xyz://q@some.host:99999" &&
- ! test-urlmatch-normalization "xyz://q@some.host:100000" &&
- ! test-urlmatch-normalization "xyz://q@some.host:100001" &&
- test-urlmatch-normalization "http://q@some.host:80" &&
- test-urlmatch-normalization "https://q@some.host:443" &&
- test-urlmatch-normalization "http://q@some.host:80/" &&
- test-urlmatch-normalization "https://q@some.host:443?" &&
- ! test-urlmatch-normalization "http://q@:8008" &&
- ! test-urlmatch-normalization "http://:8080" &&
- ! test-urlmatch-normalization "http://:" &&
- test-urlmatch-normalization "xyz://q@some.host:456/" &&
- test-urlmatch-normalization "xyz://[::1]:456/" &&
- test-urlmatch-normalization "xyz://[::1]:/" &&
- ! test-urlmatch-normalization "xyz://[::1]:000/" &&
- ! test-urlmatch-normalization "xyz://[::1]:0%300/" &&
- ! test-urlmatch-normalization "xyz://[::1]:0x80/" &&
- ! test-urlmatch-normalization "xyz://[::1]:4294967297/" &&
- ! test-urlmatch-normalization "xyz://[::1]:030f/"
+ test-tool urlmatch-normalization "xyz://q@some.host:" &&
+ test-tool urlmatch-normalization "xyz://q@some.host:456/" &&
+ ! test-tool urlmatch-normalization "xyz://q@some.host:0" &&
+ ! test-tool urlmatch-normalization "xyz://q@some.host:0000000" &&
+ test-tool urlmatch-normalization "xyz://q@some.host:0000001?" &&
+ test-tool urlmatch-normalization "xyz://q@some.host:065535#" &&
+ test-tool urlmatch-normalization "xyz://q@some.host:65535" &&
+ ! test-tool urlmatch-normalization "xyz://q@some.host:65536" &&
+ ! test-tool urlmatch-normalization "xyz://q@some.host:99999" &&
+ ! test-tool urlmatch-normalization "xyz://q@some.host:100000" &&
+ ! test-tool urlmatch-normalization "xyz://q@some.host:100001" &&
+ test-tool urlmatch-normalization "http://q@some.host:80" &&
+ test-tool urlmatch-normalization "https://q@some.host:443" &&
+ test-tool urlmatch-normalization "http://q@some.host:80/" &&
+ test-tool urlmatch-normalization "https://q@some.host:443?" &&
+ ! test-tool urlmatch-normalization "http://q@:8008" &&
+ ! test-tool urlmatch-normalization "http://:8080" &&
+ ! test-tool urlmatch-normalization "http://:" &&
+ test-tool urlmatch-normalization "xyz://q@some.host:456/" &&
+ test-tool urlmatch-normalization "xyz://[::1]:456/" &&
+ test-tool urlmatch-normalization "xyz://[::1]:/" &&
+ ! test-tool urlmatch-normalization "xyz://[::1]:000/" &&
+ ! test-tool urlmatch-normalization "xyz://[::1]:0%300/" &&
+ ! test-tool urlmatch-normalization "xyz://[::1]:0x80/" &&
+ ! test-tool urlmatch-normalization "xyz://[::1]:4294967297/" &&
+ ! test-tool urlmatch-normalization "xyz://[::1]:030f/"
'
test_expect_success 'url port normalization' '
- test "$(test-urlmatch-normalization -p "http://x:800")" = "http://x:800/" &&
- test "$(test-urlmatch-normalization -p "http://x:0800")" = "http://x:800/" &&
- test "$(test-urlmatch-normalization -p "http://x:00000800")" = "http://x:800/" &&
- test "$(test-urlmatch-normalization -p "http://x:065535")" = "http://x:65535/" &&
- test "$(test-urlmatch-normalization -p "http://x:1")" = "http://x:1/" &&
- test "$(test-urlmatch-normalization -p "http://x:80")" = "http://x/" &&
- test "$(test-urlmatch-normalization -p "http://x:080")" = "http://x/" &&
- test "$(test-urlmatch-normalization -p "http://x:000000080")" = "http://x/" &&
- test "$(test-urlmatch-normalization -p "https://x:443")" = "https://x/" &&
- test "$(test-urlmatch-normalization -p "https://x:0443")" = "https://x/" &&
- test "$(test-urlmatch-normalization -p "https://x:000000443")" = "https://x/"
+ test "$(test-tool urlmatch-normalization -p "http://x:800")" = "http://x:800/" &&
+ test "$(test-tool urlmatch-normalization -p "http://x:0800")" = "http://x:800/" &&
+ test "$(test-tool urlmatch-normalization -p "http://x:00000800")" = "http://x:800/" &&
+ test "$(test-tool urlmatch-normalization -p "http://x:065535")" = "http://x:65535/" &&
+ test "$(test-tool urlmatch-normalization -p "http://x:1")" = "http://x:1/" &&
+ test "$(test-tool urlmatch-normalization -p "http://x:80")" = "http://x/" &&
+ test "$(test-tool urlmatch-normalization -p "http://x:080")" = "http://x/" &&
+ test "$(test-tool urlmatch-normalization -p "http://x:000000080")" = "http://x/" &&
+ test "$(test-tool urlmatch-normalization -p "https://x:443")" = "https://x/" &&
+ test "$(test-tool urlmatch-normalization -p "https://x:0443")" = "https://x/" &&
+ test "$(test-tool urlmatch-normalization -p "https://x:000000443")" = "https://x/"
'
test_expect_success 'url general escapes' '
- ! test-urlmatch-normalization "http://x.y?%fg" &&
- test "$(test-urlmatch-normalization -p "X://W/%7e%41^%3a")" = "x://w/~A%5E%3A" &&
- test "$(test-urlmatch-normalization -p "X://W/:/?#[]@")" = "x://w/:/?#[]@" &&
- test "$(test-urlmatch-normalization -p "X://W/$&()*+,;=")" = "x://w/$&()*+,;=" &&
- test "$(test-urlmatch-normalization -p "X://W/'\''")" = "x://w/'\''" &&
- test "$(test-urlmatch-normalization -p "X://W?'\!'")" = "x://w/?'\!'"
+ ! test-tool urlmatch-normalization "http://x.y?%fg" &&
+ test "$(test-tool urlmatch-normalization -p "X://W/%7e%41^%3a")" = "x://w/~A%5E%3A" &&
+ test "$(test-tool urlmatch-normalization -p "X://W/:/?#[]@")" = "x://w/:/?#[]@" &&
+ test "$(test-tool urlmatch-normalization -p "X://W/$&()*+,;=")" = "x://w/$&()*+,;=" &&
+ test "$(test-tool urlmatch-normalization -p "X://W/'\''")" = "x://w/'\''" &&
+ test "$(test-tool urlmatch-normalization -p "X://W?'\!'")" = "x://w/?'\!'"
'
test_expect_success !MINGW 'url high-bit escapes' '
- test "$(test-urlmatch-normalization -p "$(cat "$tu-1")")" = "x://q/%01%02%03%04%05%06%07%08%0E%0F%10%11%12" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-2")")" = "x://q/%13%14%15%16%17%18%19%1B%1C%1D%1E%1F%7F" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-3")")" = "x://q/%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-4")")" = "x://q/%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-5")")" = "x://q/%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-6")")" = "x://q/%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-7")")" = "x://q/%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-8")")" = "x://q/%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-9")")" = "x://q/%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-10")")" = "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-1")")" = "x://q/%01%02%03%04%05%06%07%08%0E%0F%10%11%12" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-2")")" = "x://q/%13%14%15%16%17%18%19%1B%1C%1D%1E%1F%7F" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-3")")" = "x://q/%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-4")")" = "x://q/%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-5")")" = "x://q/%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-6")")" = "x://q/%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-7")")" = "x://q/%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-8")")" = "x://q/%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-9")")" = "x://q/%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" &&
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-10")")" = "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
'
test_expect_success 'url utf-8 escapes' '
- test "$(test-urlmatch-normalization -p "$(cat "$tu-11")")" = "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD"
+ test "$(test-tool urlmatch-normalization -p "$(cat "$tu-11")")" = "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD"
'
test_expect_success 'url username/password escapes' '
- test "$(test-urlmatch-normalization -p "x://%41%62(^):%70+d@foo")" = "x://Ab(%5E):p+d@foo/"
+ test "$(test-tool urlmatch-normalization -p "x://%41%62(^):%70+d@foo")" = "x://Ab(%5E):p+d@foo/"
'
test_expect_success 'url normalized lengths' '
- test "$(test-urlmatch-normalization -l "Http://%4d%65:%4d^%70@The.Host")" = 25 &&
- test "$(test-urlmatch-normalization -l "http://%41:%42@x.y/%61/")" = 17 &&
- test "$(test-urlmatch-normalization -l "http://@x.y/^")" = 15
+ test "$(test-tool urlmatch-normalization -l "Http://%4d%65:%4d^%70@The.Host")" = 25 &&
+ test "$(test-tool urlmatch-normalization -l "http://%41:%42@x.y/%61/")" = 17 &&
+ test "$(test-tool urlmatch-normalization -l "http://@x.y/^")" = 15
'
test_expect_success 'url . and .. segments' '
- test "$(test-urlmatch-normalization -p "x://y/.")" = "x://y/" &&
- test "$(test-urlmatch-normalization -p "x://y/./")" = "x://y/" &&
- test "$(test-urlmatch-normalization -p "x://y/a/.")" = "x://y/a" &&
- test "$(test-urlmatch-normalization -p "x://y/a/./")" = "x://y/a/" &&
- test "$(test-urlmatch-normalization -p "x://y/.?")" = "x://y/?" &&
- test "$(test-urlmatch-normalization -p "x://y/./?")" = "x://y/?" &&
- test "$(test-urlmatch-normalization -p "x://y/a/.?")" = "x://y/a?" &&
- test "$(test-urlmatch-normalization -p "x://y/a/./?")" = "x://y/a/?" &&
- test "$(test-urlmatch-normalization -p "x://y/a/./b/.././../c")" = "x://y/c" &&
- test "$(test-urlmatch-normalization -p "x://y/a/./b/../.././c/")" = "x://y/c/" &&
- test "$(test-urlmatch-normalization -p "x://y/a/./b/.././../c/././.././.")" = "x://y/" &&
- ! test-urlmatch-normalization "x://y/a/./b/.././../c/././.././.." &&
- test "$(test-urlmatch-normalization -p "x://y/a/./?/././..")" = "x://y/a/?/././.." &&
- test "$(test-urlmatch-normalization -p "x://y/%2e/")" = "x://y/" &&
- test "$(test-urlmatch-normalization -p "x://y/%2E/")" = "x://y/" &&
- test "$(test-urlmatch-normalization -p "x://y/a/%2e./")" = "x://y/" &&
- test "$(test-urlmatch-normalization -p "x://y/b/.%2E/")" = "x://y/" &&
- test "$(test-urlmatch-normalization -p "x://y/c/%2e%2E/")" = "x://y/"
+ test "$(test-tool urlmatch-normalization -p "x://y/.")" = "x://y/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/./")" = "x://y/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/.")" = "x://y/a" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/./")" = "x://y/a/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/.?")" = "x://y/?" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/./?")" = "x://y/?" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/.?")" = "x://y/a?" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/./?")" = "x://y/a/?" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/./b/.././../c")" = "x://y/c" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/./b/../.././c/")" = "x://y/c/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/./b/.././../c/././.././.")" = "x://y/" &&
+ ! test-tool urlmatch-normalization "x://y/a/./b/.././../c/././.././.." &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/./?/././..")" = "x://y/a/?/././.." &&
+ test "$(test-tool urlmatch-normalization -p "x://y/%2e/")" = "x://y/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/%2E/")" = "x://y/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/a/%2e./")" = "x://y/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/b/.%2E/")" = "x://y/" &&
+ test "$(test-tool urlmatch-normalization -p "x://y/c/%2e%2E/")" = "x://y/"
'
# http://@foo specifies an empty user name but does not specify a password
# http://foo specifies neither a user name nor a password
# So they should not be equivalent
test_expect_success 'url equivalents' '
- test-urlmatch-normalization "httP://x" "Http://X/" &&
- test-urlmatch-normalization "Http://%4d%65:%4d^%70@The.Host" "hTTP://Me:%4D^p@the.HOST:80/" &&
- ! test-urlmatch-normalization "https://@x.y/^" "httpS://x.y:443/^" &&
- test-urlmatch-normalization "https://@x.y/^" "httpS://@x.y:0443/^" &&
- test-urlmatch-normalization "https://@x.y/^/../abc" "httpS://@x.y:0443/abc" &&
- test-urlmatch-normalization "https://@x.y/^/.." "httpS://@x.y:0443/"
+ test-tool urlmatch-normalization "httP://x" "Http://X/" &&
+ test-tool urlmatch-normalization "Http://%4d%65:%4d^%70@The.Host" "hTTP://Me:%4D^p@the.HOST:80/" &&
+ ! test-tool urlmatch-normalization "https://@x.y/^" "httpS://x.y:443/^" &&
+ test-tool urlmatch-normalization "https://@x.y/^" "httpS://@x.y:0443/^" &&
+ test-tool urlmatch-normalization "https://@x.y/^/../abc" "httpS://@x.y:0443/abc" &&
+ test-tool urlmatch-normalization "https://@x.y/^/.." "httpS://@x.y:0443/"
'
test_done
'
test_expect_success 'setup blobs which are likely to delta' '
- test-genrandom foo 10240 >foo &&
+ test-tool genrandom foo 10240 >foo &&
{ cat foo; echo plus; } >foo-plus &&
git add foo foo-plus &&
git commit -m foo &&
. "$TEST_DIRECTORY"/lib-read-tree.sh
test_expect_success 'setup' '
+ test_commit init &&
+ echo modified >>init.t &&
+
cat >expected <<-EOF &&
- 100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t
+ 100644 $(git hash-object init.t) 0 init.t
100644 $EMPTY_BLOB 0 sub/added
100644 $EMPTY_BLOB 0 sub/addedtoo
100644 $EMPTY_BLOB 0 subsub/added
H subsub/added
EOF
- test_commit init &&
- echo modified >>init.t &&
mkdir sub subsub &&
touch sub/added sub/addedtoo subsub/added &&
git add init.t sub/added sub/addedtoo subsub/added &&
# mid1 and mid2 will fit within 256k limit but
# appending mid3 will bust the limit and will
# result in a separate packfile.
- test-genrandom "a" $(( 66 * 1024 )) >mid1 &&
- test-genrandom "b" $(( 80 * 1024 )) >mid2 &&
- test-genrandom "c" $(( 128 * 1024 )) >mid3 &&
+ test-tool genrandom "a" $(( 66 * 1024 )) >mid1 &&
+ test-tool genrandom "b" $(( 80 * 1024 )) >mid2 &&
+ test-tool genrandom "c" $(( 128 * 1024 )) >mid3 &&
git add mid1 mid2 mid3 &&
count=0
invalid1 = "abc"
EOF
cat >expect <<-EOF &&
- $(test-date timestamp $rel)
+ $(test-tool date timestamp $rel)
1275666415
1510441871
1510348087
'
test_expect_success !MINGW '--show-origin blob' '
- cat >expect <<-\EOF &&
- blob:a9d9f9e555b5c6f07cbe09d3f06fe3df11e09c08 user.custom=true
- EOF
blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+ cat >expect <<-EOF &&
+ blob:$blob user.custom=true
+ EOF
git config --blob=$blob --show-origin --list >output &&
test_cmp expect output
'
test_expect_success SETFACL 'Objects creation does not break ACLs with restrictive umask' '
# SHA1 for empty blob
- check_perms_and_acl .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
+ check_perms_and_acl .git/objects/$(echo $EMPTY_BLOB | sed -e "s,^\(..\),\1/,")
'
test_expect_success SETFACL 'git gc does not break ACLs with restrictive umask' '
echo "[includeIf \"gitdir:foo/\"]path=bar6" >>.git/config &&
echo "[test]six=6" >.git/bar6 &&
echo 6 >expect &&
- test-config read_early_config test.six >actual &&
+ test-tool config read_early_config test.six >actual &&
test_cmp expect actual
)
'
then
printf "%s\n" "$@"
fi >expect &&
- test_expect_code $expect_code test-config "$op" "$key" >actual &&
+ test_expect_code $expect_code test-tool config "$op" "$key" >actual &&
test_cmp expect actual
}
'
test_expect_success 'check line error when NULL string is queried' '
- test_expect_code 128 test-config get_string case.foo 2>result &&
+ test_expect_code 128 test-tool config get_string case.foo 2>result &&
test_i18ngrep "fatal: .*case\.foo.*\.git/config.*line 7" result
'
baz = ball
EOF
echo silk >expect &&
- test-config configset_get_value my.new config2 .git/config >actual &&
+ test-tool config configset_get_value my.new config2 .git/config >actual &&
test_cmp expect actual
'
test_expect_success 'find value with highest priority from a configset' '
echo hask >expect &&
- test-config configset_get_value case.baz config2 .git/config >actual &&
+ test-tool config configset_get_value case.baz config2 .git/config >actual &&
test_cmp expect actual
'
lama
ball
EOF
- test-config configset_get_value case.baz config2 .git/config >actual &&
+ test-tool config configset_get_value case.baz config2 .git/config >actual &&
test_cmp expect actual
'
test_expect_success 'proper error on non-existent files' '
echo "Error (-1) reading configuration file non-existent-file." >expect &&
- test_expect_code 2 test-config configset_get_value foo.bar non-existent-file 2>actual &&
+ test_expect_code 2 test-tool config configset_get_value foo.bar non-existent-file 2>actual &&
test_cmp expect actual
'
test_expect_success 'proper error on directory "files"' '
echo "Error (-1) reading configuration file a-directory." >expect &&
mkdir a-directory &&
- test_expect_code 2 test-config configset_get_value foo.bar a-directory 2>output &&
+ test_expect_code 2 test-tool config configset_get_value foo.bar a-directory 2>output &&
grep "^warning:" output &&
grep "^Error" output >actual &&
test_cmp expect actual
chmod -r .git/config &&
test_when_finished "chmod +r .git/config" &&
echo "Error (-1) reading configuration file .git/config." >expect &&
- test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>output &&
+ test_expect_code 2 test-tool config configset_get_value foo.bar .git/config 2>output &&
grep "^warning:" output &&
grep "^Error" output >actual &&
test_cmp expect actual
test_when_finished "mv .git/config.old .git/config" &&
echo "[" >>.git/config &&
echo "fatal: bad config line 34 in file .git/config" >expect &&
- test_expect_code 128 test-config get_value foo.bar 2>actual &&
+ test_expect_code 128 test-tool config get_value foo.bar 2>actual &&
test_i18ncmp expect actual
'
test_expect_success 'proper error on error in custom config files' '
echo "[" >>syntax-error &&
echo "fatal: bad config line 1 in file syntax-error" >expect &&
- test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual &&
+ test_expect_code 128 test-tool config configset_get_value foo.bar syntax-error 2>actual &&
test_i18ncmp expect actual
'
name=
scope=cmdline
EOF
- GIT_CONFIG_PARAMETERS=$cmdline_config test-config iterate >actual &&
+ GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
test_cmp expect actual
'
test_expect_success 'read early config' '
test_config early.config correct &&
- test-config read_early_config early.config >output &&
+ test-tool config read_early_config early.config >output &&
test correct = "$(cat output)"
'
mkdir -p sub &&
(
cd sub &&
- test-config read_early_config early.config
+ test-tool config read_early_config early.config
) >output &&
test sub = "$(cat output)"
'
GIT_CEILING_DIRECTORIES="$PWD" &&
export GIT_CEILING_DIRECTORIES &&
cd sub &&
- test-config read_early_config early.config
+ test-tool config read_early_config early.config
) >output &&
test -z "$(cat output)"
'
GIT_CEILING_DIRECTORIES="$PWD" &&
export GIT_CEILING_DIRECTORIES XDG_CONFIG_HOME &&
cd sub &&
- test-config read_early_config early.config
+ test-tool config read_early_config early.config
) >output &&
test xdg = "$(cat output)"
'
(
cd foo &&
echo "[test]source = repo" >>.git/config &&
- GIT_CONFIG_PARAMETERS=$cmdline_config test-config \
+ GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config \
read_early_config test.source >actual &&
cat >expected <<-\EOF &&
home
(
cd throwaway &&
echo "$*" >.git/config &&
- test-config read_early_config early.config
+ test-tool config read_early_config early.config
)
}
. ./test-lib.sh
-RUN="test-ref-store main"
+RUN="test-tool ref-store main"
test_expect_success 'pack_refs(PACK_REFS_ALL | PACK_REFS_PRUNE)' '
test_commit one &&
'
test_expect_success 'for_each_ref(refs/heads/)' '
- $RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
+ $RUN for-each-ref refs/heads/ | cut -d" " -f 2- >actual &&
cat >expected <<-\EOF &&
master 0x0
new-master 0x0
'
test_expect_success 'for_each_reflog()' '
- $RUN for-each-reflog | sort | cut -c 42- >actual &&
+ $RUN for-each-reflog | sort -k2 | cut -c 42- >actual &&
cat >expected <<-\EOF &&
HEAD 0x1
refs/heads/master 0x0
. ./test-lib.sh
-RUN="test-ref-store submodule:sub"
+RUN="test-tool ref-store submodule:sub"
test_expect_success 'setup' '
git init sub &&
. ./test-lib.sh
-RWT="test-ref-store worktree:wt"
-RMAIN="test-ref-store worktree:main"
+RWT="test-tool ref-store worktree:wt"
+RMAIN="test-tool ref-store worktree:main"
test_expect_success 'setup' '
test_commit first &&
git commit -m one
'
+commit=$(git rev-parse --short HEAD)
cat >expect <<'EOF'
Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
Reflog message: commit (initial): one
test_cmp expect actual
'
-cat >expect <<'EOF'
-e46513e HEAD@{0}: commit (initial): one
+cat >expect <<EOF
+$commit HEAD@{0}: commit (initial): one
EOF
test_expect_success 'oneline reflog format' '
git log -g -1 --oneline >actual &&
test_cmp expect actual
'
-cat >expect <<'EOF'
-commit e46513e
+cat >expect <<EOF
+commit $commit
Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
Reflog message: commit (initial): one
Author: A U Thor <author@example.com>
test_cmp expect actual
'
-cat >expect <<'EOF'
-e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
+cat >expect <<EOF
+$commit HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
EOF
test_expect_success 'using @{now} syntax shows reflog date (oneline)' '
git log -g -1 --oneline HEAD@{now} >actual &&
test_cmp expect actual
'
-cat >expect <<'EOF'
-e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
+cat >expect <<EOF
+$commit HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
EOF
test_expect_success 'using --date= shows reflog date (oneline)' '
git log -g -1 --oneline --date=default >actual &&
test_cmp expect actual
'
-cat >expect <<'EOF'
-e46513e HEAD@{0}: commit (initial): one
+cat >expect <<EOF
+$commit HEAD@{0}: commit (initial): one
EOF
test_expect_success 'log.date does not invoke "--date" magic (oneline)' '
test_config log.date raw &&
test_expect_success 'relative $GIT_WORK_TREE and git subprocesses' '
GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \
- test-subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
+ test-tool subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
echo "$(pwd)/repo.git/work" >expected &&
test_cmp expected actual
'
(
cd work &&
GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
- test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
+ test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
test_cmp expect actual
)
'
(
cd work &&
GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
- test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
+ test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
test_cmp expect actual
)
'
(
cd work &&
git rev-parse --git-common-dir >actual &&
- test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
+ test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
test_cmp expect actual &&
echo haha >data1 &&
git add data1 &&
(
cd work &&
git rev-parse --git-common-dir >actual &&
- test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
+ test-tool path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
test_cmp expect actual &&
echo haha >data2 &&
git add data2 &&
test refs/heads/master = "$(full_name @{u})"
'
+commit=$(git rev-parse HEAD)
cat >expect <<EOF
-commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
+commit $commit
Reflog: master@{0} (C O Mitter <committer@example.com>)
Reflog message: branch: Created from HEAD
Author: A U Thor <author@example.com>
'
cat >expect <<EOF
-commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
+commit $commit
Reflog: master@{Thu Apr 7 15:17:13 2005 -0700} (C O Mitter <committer@example.com>)
Reflog message: branch: Created from HEAD
Author: A U Thor <author@example.com>
git config --add index.version 2 &&
git add a 2>&1 &&
echo 4 >expect &&
- test-index-version <.git/index >actual &&
+ test-tool index-version <.git/index >actual &&
test_cmp expect actual
)
'
test_expect_success 'enable split index' '
git config splitIndex.maxPercentChange 100 &&
git update-index --split-index &&
- test-dump-split-index .git/index >actual &&
- indexversion=$(test-index-version <.git/index) &&
+ test-tool dump-split-index .git/index >actual &&
+ indexversion=$(test-tool index-version <.git/index) &&
if test "$indexversion" = "4"
then
own=432ef4b63f32193984f339431fd50ca796493569
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
base $base
100644 $EMPTY_BLOB 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
- BASE=$(test-dump-split-index .git/index | grep "^own" | sed "s/own/base/") &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ BASE=$(test-tool dump-split-index .git/index | grep "^own" | sed "s/own/base/") &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
not a split index
EOF
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
replacements:
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
q_to_tab >expect <<-EOF &&
$BASE
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
q_to_tab >expect <<-EOF &&
$BASE
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
q_to_tab >expect <<-EOF &&
$BASE
100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
replacements:
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
100644 $EMPTY_BLOB 0 one
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
not a split index
EOF
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
EOF
test_cmp ls-files.expect ls-files.actual &&
- BASE=$(test-dump-split-index .git/index | grep "^base") &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
replacements:
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
EOF
test_cmp ls-files.expect ls-files.actual &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
not a split index
EOF
git config core.splitIndex true &&
: >three &&
git update-index --add three &&
- BASE=$(test-dump-split-index .git/index | grep "^base") &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
replacements:
test_cmp expect actual &&
: >four &&
git update-index --add four &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 four
git config --unset splitIndex.maxPercentChange &&
: >five &&
git update-index --add five &&
- BASE=$(test-dump-split-index .git/index | grep "^base") &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
replacements:
test_cmp expect actual &&
: >six &&
git update-index --add six &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 six
git config splitIndex.maxPercentChange 0 &&
: >seven &&
git update-index --add seven &&
- BASE=$(test-dump-split-index .git/index | grep "^base") &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
replacements:
test_cmp expect actual &&
: >eight &&
git update-index --add eight &&
- BASE=$(test-dump-split-index .git/index | grep "^base") &&
- test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ BASE=$(test-tool dump-split-index .git/index | grep "^base") &&
+ test-tool dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<-EOF &&
$BASE
replacements:
git update-index --add ten &&
test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
just_under_2_weeks_ago=$((5-14*86400)) &&
- test-chmtime =$just_under_2_weeks_ago .git/sharedindex.* &&
+ test-tool chmtime =$just_under_2_weeks_ago .git/sharedindex.* &&
: >eleven &&
git update-index --add eleven &&
test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
just_over_2_weeks_ago=$((-1-14*86400)) &&
- test-chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
+ test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
: >twelve &&
git update-index --add twelve &&
test $(ls .git/sharedindex.* | wc -l) -le 2
test_expect_success 'check splitIndex.sharedIndexExpire set to 16 days' '
git config splitIndex.sharedIndexExpire "16.days.ago" &&
- test-chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
+ test-tool chmtime =$just_over_2_weeks_ago .git/sharedindex.* &&
: >thirteen &&
git update-index --add thirteen &&
test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
just_over_16_days_ago=$((-1-16*86400)) &&
- test-chmtime =$just_over_16_days_ago .git/sharedindex.* &&
+ test-tool chmtime =$just_over_16_days_ago .git/sharedindex.* &&
: >fourteen &&
git update-index --add fourteen &&
test $(ls .git/sharedindex.* | wc -l) -le 2
test_expect_success 'check splitIndex.sharedIndexExpire set to "never" and "now"' '
git config splitIndex.sharedIndexExpire never &&
just_10_years_ago=$((-365*10*86400)) &&
- test-chmtime =$just_10_years_ago .git/sharedindex.* &&
+ test-tool chmtime =$just_10_years_ago .git/sharedindex.* &&
: >fifteen &&
git update-index --add fifteen &&
test $(ls .git/sharedindex.* | wc -l) -gt 2 &&
git config splitIndex.sharedIndexExpire now &&
just_1_second_ago=-1 &&
- test-chmtime =$just_1_second_ago .git/sharedindex.* &&
+ test-tool chmtime =$just_1_second_ago .git/sharedindex.* &&
: >sixteen &&
git update-index --add sixteen &&
test $(ls .git/sharedindex.* | wc -l) -le 2
commit=$(git commit-tree $tree -p HEAD <msg) &&
git update-ref HEAD "$commit" &&
GIT_ALLOW_NULL_SHA1=1 git reset --hard &&
- (test-dump-cache-tree >cache-tree.out || true) &&
+ (test-tool dump-cache-tree >cache-tree.out || true) &&
test_line_count = 0 cache-tree.out
'
# Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (new format)
test_expect_success 'describe_detached_head prints no SHA-1 ellipsis when not asked to' "
+ commit=$(git rev-parse --short=12 master^) &&
+ commit2=$(git rev-parse --short=12 master~2) &&
+ commit3=$(git rev-parse --short=12 master~3) &&
+
# The first detach operation is more chatty than the following ones.
- cat >1st_detach <<-'EOF' &&
+ cat >1st_detach <<-EOF &&
Note: checking out 'HEAD^'.
You are in 'detached HEAD' state. You can look around, make experimental
git checkout -b <new-branch-name>
- HEAD is now at 7c7cd714e262 three
+ HEAD is now at \$commit three
EOF
# The remaining ones just show info about previous and current HEADs.
- cat >2nd_detach <<-'EOF' &&
- Previous HEAD position was 7c7cd714e262 three
- HEAD is now at 139b20d8e6c5 two
+ cat >2nd_detach <<-EOF &&
+ Previous HEAD position was \$commit three
+ HEAD is now at \$commit2 two
EOF
- cat >3rd_detach <<-'EOF' &&
- Previous HEAD position was 139b20d8e6c5 two
- HEAD is now at d79ce1670bdc one
+ cat >3rd_detach <<-EOF &&
+ Previous HEAD position was \$commit2 two
+ HEAD is now at \$commit3 one
EOF
reset &&
# Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (old format)
test_expect_success 'describe_detached_head does print SHA-1 ellipsis when asked to' "
+ commit=$(git rev-parse --short=12 master^) &&
+ commit2=$(git rev-parse --short=12 master~2) &&
+ commit3=$(git rev-parse --short=12 master~3) &&
+
# The first detach operation is more chatty than the following ones.
- cat >1st_detach <<-'EOF' &&
+ cat >1st_detach <<-EOF &&
Note: checking out 'HEAD^'.
You are in 'detached HEAD' state. You can look around, make experimental
git checkout -b <new-branch-name>
- HEAD is now at 7c7cd714e262... three
+ HEAD is now at \$commit... three
EOF
# The remaining ones just show info about previous and current HEADs.
- cat >2nd_detach <<-'EOF' &&
- Previous HEAD position was 7c7cd714e262... three
- HEAD is now at 139b20d8e6c5... two
+ cat >2nd_detach <<-EOF &&
+ Previous HEAD position was \$commit... three
+ HEAD is now at \$commit2... two
EOF
- cat >3rd_detach <<-'EOF' &&
- Previous HEAD position was 139b20d8e6c5... two
- HEAD is now at d79ce1670bdc... one
+ cat >3rd_detach <<-EOF &&
+ Previous HEAD position was \$commit2... two
+ HEAD is now at \$commit3... one
EOF
reset &&
git add file1 file2 &&
git commit -m base &&
echo modified >file1 &&
- test-chmtime =1000000000 file2 &&
+ test-tool chmtime =1000000000 file2 &&
git update-index -q --refresh &&
git checkout HEAD -- file1 file2 &&
echo one >expect &&
test_cmp expect file1 &&
echo "1000000000 file2" >expect &&
- test-chmtime -v +0 file2 >actual &&
+ test-tool chmtime -v +0 file2 >actual &&
test_cmp expect actual
'
test_expect_success 'not prune recent checkouts' '
test_when_finished rm -r .git/worktrees &&
- mkdir zz &&
- mkdir -p .git/worktrees/jlm &&
- echo "$(pwd)"/zz >.git/worktrees/jlm/gitdir &&
- rmdir zz &&
+ git worktree add jlm HEAD &&
+ test -d .git/worktrees/jlm &&
+ rm -rf jlm &&
git worktree prune --verbose --expire=2.days.ago &&
test -d .git/worktrees/jlm
'
. ./test-lib.sh
-cat > expected <<\EOF
-100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0 file1
-100644 9db8893856a8a02eaa73470054b7c1c5a7c82e47 0 file2
-EOF
-test_expect_success 'update-index --add' \
- 'echo hello world >file1 &&
- echo goodbye people >file2 &&
- git update-index --add file1 file2 &&
- git ls-files -s >current &&
- cmp current expected'
+test_expect_success 'update-index --add' '
+ echo hello world >file1 &&
+ echo goodbye people >file2 &&
+ git update-index --add file1 file2 &&
+ git ls-files -s >current &&
+ cat >expected <<-EOF &&
+ 100644 $(git hash-object file1) 0 file1
+ 100644 $(git hash-object file2) 0 file2
+ EOF
+ cmp current expected
+'
-test_expect_success 'update-index --again' \
- 'rm -f file1 &&
+test_expect_success 'update-index --again' '
+ rm -f file1 &&
echo hello everybody >file2 &&
if git update-index --again
then
else
echo happy - failed as expected
fi &&
- git ls-files -s >current &&
- cmp current expected'
+ git ls-files -s >current &&
+ cmp current expected
+'
-cat > expected <<\EOF
-100644 0f1ae1422c2bf43f117d3dbd715c988a9ed2103f 0 file2
-EOF
-test_expect_success 'update-index --remove --again' \
- 'git update-index --remove --again &&
- git ls-files -s >current &&
- cmp current expected'
+test_expect_success 'update-index --remove --again' '
+ git update-index --remove --again &&
+ git ls-files -s >current &&
+ cat >expected <<-EOF &&
+ 100644 $(git hash-object file2) 0 file2
+ EOF
+ cmp current expected
+'
test_expect_success 'first commit' 'git commit -m initial'
-cat > expected <<\EOF
-100644 53ab446c3f4e42ce9bb728a0ccb283a101be4979 0 dir1/file3
-100644 0f1ae1422c2bf43f117d3dbd715c988a9ed2103f 0 file2
-EOF
-test_expect_success 'update-index again' \
- 'mkdir -p dir1 &&
+test_expect_success 'update-index again' '
+ mkdir -p dir1 &&
echo hello world >dir1/file3 &&
echo goodbye people >file2 &&
git update-index --add file2 dir1/file3 &&
echo happy >dir1/file3 &&
git update-index --again &&
git ls-files -s >current &&
- cmp current expected'
+ cat >expected <<-EOF &&
+ 100644 $(git hash-object dir1/file3) 0 dir1/file3
+ 100644 $(git hash-object file2) 0 file2
+ EOF
+ cmp current expected
+'
-cat > expected <<\EOF
-100644 d7fb3f695f06c759dbf3ab00046e7cc2da22d10f 0 dir1/file3
-100644 0f1ae1422c2bf43f117d3dbd715c988a9ed2103f 0 file2
-EOF
-test_expect_success 'update-index --update from subdir' \
- 'echo not so happy >file2 &&
+file2=$(git hash-object file2)
+test_expect_success 'update-index --update from subdir' '
+ echo not so happy >file2 &&
(cd dir1 &&
cat ../file2 >file3 &&
git update-index --again
) &&
git ls-files -s >current &&
- cmp current expected'
+ cat >expected <<-EOF &&
+ 100644 $(git hash-object dir1/file3) 0 dir1/file3
+ 100644 $file2 0 file2
+ EOF
+ test_cmp current expected
+'
-cat > expected <<\EOF
-100644 594fb5bb1759d90998e2bf2a38261ae8e243c760 0 dir1/file3
-100644 0f1ae1422c2bf43f117d3dbd715c988a9ed2103f 0 file2
-EOF
-test_expect_success 'update-index --update with pathspec' \
- 'echo very happy >file2 &&
+test_expect_success 'update-index --update with pathspec' '
+ echo very happy >file2 &&
cat file2 >dir1/file3 &&
git update-index --again dir1/ &&
git ls-files -s >current &&
- cmp current expected'
+ cat >expected <<-EOF &&
+ 100644 $(git hash-object dir1/file3) 0 dir1/file3
+ 100644 $file2 0 file2
+ EOF
+ cmp current expected
+'
test_done
'
test_expect_success 'index is at version 2' '
- test "$(test-index-version < .git/index)" = 2
+ test "$(test-tool index-version < .git/index)" = 2
'
test_expect_success 'update-index --skip-worktree' '
'
test_expect_success 'index is at version 3 after having some skip-worktree entries' '
- test "$(test-index-version < .git/index)" = 3
+ test "$(test-tool index-version < .git/index)" = 3
'
test_expect_success 'ls-files -t' '
'
test_expect_success 'index version is back to 2 when there is no skip-worktree entry' '
- test "$(test-index-version < .git/index)" = 2
+ test "$(test-tool index-version < .git/index)" = 2
'
test_done
>B &&
git add A B &&
git update-index --chmod=+x A --chmod=-x B &&
- cat >expect <<-\EOF &&
- 100755 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 A
- 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 B
+ cat >expect <<-EOF &&
+ 100755 $EMPTY_BLOB 0 A
+ 100644 $EMPTY_BLOB 0 B
EOF
git ls-files --stage A B >actual &&
test_cmp expect actual
. ./test-lib.sh
-if test 1 -eq $($GIT_BUILD_DIR/t/helper/test-online-cpus)
+if test 1 -eq $($GIT_BUILD_DIR/t/helper/test-tool online-cpus)
then
skip_all='skipping lazy-init tests, single cpu'
test_done
) |
sed "s/^/100644 $EMPTY_BLOB /" |
git update-index --index-info &&
- test-lazy-init-name-hash -m
+ test-tool lazy-init-name-hash -m
'
test_done
if test "$match_expect" = 1
then
test_expect_success "$match_function: match '$text' '$pattern'" "
- test-wildmatch $match_function '$text' '$pattern'
+ test-tool wildmatch $match_function '$text' '$pattern'
"
elif test "$match_expect" = 0
then
test_expect_success "$match_function: no match '$text' '$pattern'" "
- test_must_fail test-wildmatch $match_function '$text' '$pattern'
+ test_must_fail test-tool wildmatch $match_function '$text' '$pattern'
"
else
test_expect_success "PANIC: Test framework error. Unknown matches value $match_expect" 'false'
match() {
if test "$#" = 6
then
- # When test-wildmatch and git ls-files produce the same
+ # When test-tool wildmatch and git ls-files produce the same
# result.
match_glob=$1
match_file_glob=$match_glob
fi
'
- # $1: Case sensitive glob match: test-wildmatch & ls-files
+ # $1: Case sensitive glob match: test-tool wildmatch & ls-files
match_with_function "$text" "$pattern" $match_glob "wildmatch"
match_with_ls_files "$text" "$pattern" $match_file_glob "wildmatch" " --glob-pathspecs"
- # $2: Case insensitive glob match: test-wildmatch & ls-files
+ # $2: Case insensitive glob match: test-tool wildmatch & ls-files
match_with_function "$text" "$pattern" $match_iglob "iwildmatch"
match_with_ls_files "$text" "$pattern" $match_file_iglob "iwildmatch" " --glob-pathspecs --icase-pathspecs"
- # $3: Case sensitive path match: test-wildmatch & ls-files
+ # $3: Case sensitive path match: test-tool wildmatch & ls-files
match_with_function "$text" "$pattern" $match_pathmatch "pathmatch"
match_with_ls_files "$text" "$pattern" $match_file_pathmatch "pathmatch" ""
- # $4: Case insensitive path match: test-wildmatch & ls-files
+ # $4: Case insensitive path match: test-tool wildmatch & ls-files
match_with_function "$text" "$pattern" $match_pathmatchi "ipathmatch"
match_with_ls_files "$text" "$pattern" $match_file_pathmatchi "ipathmatch" " --icase-pathspecs"
}
git commit -m 3rd &&
COMMIT_FILE=.git/objects/5e/e1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
test -f $COMMIT_FILE &&
- test-chmtime =+0 $COMMIT_FILE &&
+ test-tool chmtime =+0 $COMMIT_FILE &&
git notes add -m "Note #3"
'
test_expect_success 'avoid unnecessary reset' '
git checkout master &&
git reset --hard &&
- test-chmtime =123456789 file3 &&
+ test-tool chmtime =123456789 file3 &&
git update-index --refresh &&
HEAD=$(git rev-parse HEAD) &&
set_fake_editor &&
git rebase -i HEAD~4 &&
test $HEAD = $(git rev-parse HEAD) &&
- MTIME=$(test-chmtime -v +0 file3 | sed 's/[^0-9].*$//') &&
+ MTIME=$(test-tool chmtime -v +0 file3 | sed 's/[^0-9].*$//') &&
test 123456789 = $MTIME
'
test_expect_success 'rebase -i --exec without <CMD>' '
git reset --hard execute &&
set_fake_editor &&
- test_must_fail git rebase -i --exec 2>tmp &&
- sed -e "1d" tmp >actual &&
- test_must_fail git rebase -h >expected &&
- test_cmp expected actual &&
+ test_must_fail git rebase -i --exec 2>actual &&
+ test_i18ngrep "requires a value" actual &&
git checkout master
'
git checkout master &&
FAKE_LINES="edit 1" git rebase -i HEAD^ &&
- test-chmtime =-60 F1 &&
+ test-tool chmtime =-60 F1 &&
git rebase --continue
'
test_must_fail git rebase --onto master master topic &&
echo "Resolved" >F2 &&
git add F2 &&
- test-chmtime =-60 F1 &&
+ test-tool chmtime =-60 F1 &&
git rebase --continue
'
(
cd copy &&
git checkout initial &&
- test-chmtime +40 oops &&
+ test-tool chmtime +40 oops &&
git cherry-pick added
)
'
test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
pristine_detach initial &&
test_expect_code 1 git cherry-pick base..anotherpick &&
- test-chmtime -v +0 .git/sequencer >expect &&
+ test-tool chmtime -v +0 .git/sequencer >expect &&
test_expect_code 128 git cherry-pick unrelatedpick &&
- test-chmtime -v +0 .git/sequencer >actual &&
+ test-tool chmtime -v +0 .git/sequencer >actual &&
test_cmp expect actual
'
test_expect_success 'refresh index before checking if it is up-to-date' '
git reset --hard &&
- test-chmtime -86400 frotz/nitfol &&
+ test-tool chmtime -86400 frotz/nitfol &&
git rm frotz/nitfol &&
test ! -f frotz/nitfol
echo >foo && echo >bar && echo >baz &&
git add foo bar baz && H=$(git rev-parse :foo) && git rm -f foo &&
echo "100644 $H 3 foo" | git update-index --index-info &&
- test-chmtime -60 bar baz &&
+ test-tool chmtime -60 bar baz &&
>expect &&
git add --refresh bar >actual &&
test_cmp expect actual &&
test_path_is_file ignored.d/foo
'
+test_expect_success 'stash -u -- <untracked> doesnt print error' '
+ >untracked &&
+ git stash push -u -- untracked 2>actual &&
+ test_path_is_missing untracked &&
+ test_line_count = 0 actual
+'
+
+test_expect_success 'stash -u -- <untracked> leaves rest of working tree in place' '
+ >tracked &&
+ git add tracked &&
+ >untracked &&
+ git stash push -u -- untracked &&
+ test_path_is_missing untracked &&
+ test_path_is_file tracked
+'
+
+test_expect_success 'stash -u -- <tracked> <untracked> clears changes in both' '
+ >tracked &&
+ git add tracked &&
+ >untracked &&
+ git stash push -u -- tracked untracked &&
+ test_path_is_missing tracked &&
+ test_path_is_missing untracked
+'
+
+test_expect_success 'stash --all -- <ignored> stashes ignored file' '
+ >ignored.d/bar &&
+ git stash push --all -- ignored.d/bar &&
+ test_path_is_missing ignored.d/bar
+'
+
+test_expect_success 'stash --all -- <tracked> <ignored> clears changes in both' '
+ >tracked &&
+ git add tracked &&
+ >ignored.d/bar &&
+ git stash push --all -- tracked ignored.d/bar &&
+ test_path_is_missing tracked &&
+ test_path_is_missing ignored.d/bar
+'
+
+test_expect_success 'stash -u -- <ignored> leaves ignored file alone' '
+ >ignored.d/bar &&
+ git stash push -u -- ignored.d/bar &&
+ test_path_is_file ignored.d/bar
+'
+
+test_expect_success 'stash -u -- <non-existant> shows no changes when there are none' '
+ git stash push -u -- non-existant >actual &&
+ echo "No local changes to save" >expect &&
+ test_i18ncmp expect actual
+'
+
test_done
>expected &&
rm -f frotz nitfol &&
echo xyzzy >nitfol &&
- test-chmtime +10 nitfol &&
+ test-tool chmtime +10 nitfol &&
if test_have_prereq SYMLINKS
then
ln -s xyzzy frotz
mkdir dir3 &&
cp dir/sub dir3/sub &&
- test-chmtime +1 dir3/sub &&
+ test-tool chmtime +1 dir3/sub &&
git config log.showroot false &&
git commit --amend &&
'
test_expect_success 'git diff --quiet ignores stat-change only entries' '
- test-chmtime +10 a &&
+ test-tool chmtime +10 a &&
echo modified >>b &&
test_expect_code 1 git diff --quiet
'
git checkout -f --orphan skip-stat-info &&
git reset &&
test_commit skip-should-be-untouched &&
- test-chmtime =0 skip-should-be-untouched.t &&
+ test-tool chmtime =0 skip-should-be-untouched.t &&
git update-index --refresh &&
git diff-files --exit-code --quiet &&
test_must_fail git am 0001-*.patch &&
git checkout -f --orphan abort-stat-info &&
git reset &&
test_commit abort-should-be-untouched &&
- test-chmtime =0 abort-should-be-untouched.t &&
+ test-tool chmtime =0 abort-should-be-untouched.t &&
git update-index --refresh &&
git diff-files --exit-code --quiet &&
test_must_fail git am 0001-*.patch &&
git commit -q -a -m "prefer first over second" &&
test -f $rr/postimage &&
- oldmtimepost=$(test-chmtime -v -60 $rr/postimage | cut -f 1) &&
+ oldmtimepost=$(test-tool chmtime -v -60 $rr/postimage | cut -f 1) &&
git checkout -b third master &&
git show second^:a1 | sed "s/To die: t/To die! T/" >a1 &&
'
test_expect_success 'rerere updates postimage timestamp' '
- newmtimepost=$(test-chmtime -v +0 $rr/postimage | cut -f 1) &&
+ newmtimepost=$(test-tool chmtime -v +0 $rr/postimage | cut -f 1) &&
test $oldmtimepost -lt $newmtimepost
'
almost_60_days_ago=$((60-60*86400)) &&
just_over_60_days_ago=$((-1-60*86400)) &&
- test-chmtime =$just_over_60_days_ago $rr/preimage &&
- test-chmtime =$almost_60_days_ago $rr/postimage &&
- test-chmtime =$almost_15_days_ago $rr2/preimage
+ test-tool chmtime =$just_over_60_days_ago $rr/preimage &&
+ test-tool chmtime =$almost_60_days_ago $rr/postimage &&
+ test-tool chmtime =$almost_15_days_ago $rr2/preimage
'
test_expect_success 'gc preserves young or recently used records' '
'
test_expect_success 'old records rest in peace' '
- test-chmtime =$just_over_60_days_ago $rr/postimage &&
- test-chmtime =$just_over_15_days_ago $rr2/preimage &&
+ test-tool chmtime =$just_over_60_days_ago $rr/postimage &&
+ test-tool chmtime =$just_over_15_days_ago $rr2/preimage &&
git rerere gc &&
! test -f $rr/preimage &&
! test -f $rr2/preimage
>"$rr/postimage" &&
two_days_ago=$((-2*86400)) &&
- test-chmtime =$two_days_ago "$rr/preimage" &&
- test-chmtime =$two_days_ago "$rr/postimage" &&
+ test-tool chmtime =$two_days_ago "$rr/preimage" &&
+ test-tool chmtime =$two_days_ago "$rr/postimage" &&
find .git/rr-cache -type f | sort >original &&
count_pre_post 2 0 &&
# Pretend that the conflicts were made quite some time ago
- find .git/rr-cache/ -type f | xargs test-chmtime -172800 &&
+ find .git/rr-cache/ -type f | xargs test-tool chmtime -172800 &&
# Unresolved entries have not expired yet
git -c gc.rerereresolved=5 -c gc.rerereunresolved=5 rerere gc &&
git rerere &&
# Pretend that the resolutions are old again
- find .git/rr-cache/ -type f | xargs test-chmtime -172800 &&
+ find .git/rr-cache/ -type f | xargs test-tool chmtime -172800 &&
# Resolved entries have not expired yet
git -c gc.rerereresolved=5 -c gc.rerereunresolved=5 rerere gc &&
test_cmp expect out
'
+test_expect_success 'shortlog from non-git directory refuses extra arguments' '
+ test_must_fail env GIT_DIR=non-existing git shortlog foo 2>out &&
+ test_i18ngrep "too many arguments" out
+'
+
test_expect_success 'shortlog should add newline when input line matches wraplen' '
cat >expect <<\EOF &&
A U Thor (2):
ten=0123456789 && hundred=$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten &&
echo long filename >a/four$hundred &&
mkdir a/bin &&
- test-genrandom "frotz" 500000 >a/bin/sh &&
+ test-tool genrandom "frotz" 500000 >a/bin/sh &&
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
printf "A not substituted O" >a/substfile2 &&
if test_have_prereq SYMLINKS; then
'validate file modification time' \
'mkdir extract &&
"$TAR" xf b.tar -C extract a/a &&
- test-chmtime -v +0 extract/a/a |cut -f 1 >b.mtime &&
+ test-tool chmtime -v +0 extract/a/a |cut -f 1 >b.mtime &&
echo "1117231200" >expected.mtime &&
test_cmp expected.mtime b.mtime'
perl -e "print \"a\" x 4096;" > a &&
perl -e "print \"b\" x 4096;" > b &&
perl -e "print \"c\" x 4096;" > c &&
- test-genrandom "seed a" 2097152 > a_big &&
- test-genrandom "seed b" 2097152 > b_big &&
+ test-tool genrandom "seed a" 2097152 > a_big &&
+ test-tool genrandom "seed b" 2097152 > b_big &&
git update-index --add a a_big b b_big c &&
cat c >d && echo foo >>d && git update-index --add d &&
tree=$(git write-tree) &&
rm -f .git/index &&
tail -n 10 LIST | git update-index --index-info &&
ST=$(git write-tree) &&
- PACK5=$( git rev-list --objects "$LIST" "$LI" "$ST" | \
- git pack-objects test-5 ) &&
+ git rev-list --objects "$LIST" "$LI" "$ST" >actual &&
+ PACK5=$( git pack-objects test-5 <actual ) &&
PACK6=$( (
echo "$LIST"
echo "$LI"
rm -f .git/index &&
tail -n 10 LIST | git update-index --index-info &&
ST=$(git write-tree) &&
- PACK5=$( git rev-list --objects "$LIST" "$LI" "$ST" | \
- git pack-objects test-5 ) &&
+ git rev-list --objects "$LIST" "$LI" "$ST" >actual &&
+ PACK5=$( git pack-objects test-5 <actual ) &&
PACK6=$( (
echo "$LIST"
echo "$LI"
for i in a b c
do
echo $i >$i &&
- test-genrandom "$i" 32768 >>$i &&
+ test-tool genrandom "$i" 32768 >>$i &&
git update-index --add $i || return 1
done &&
echo d >d && cat c >>d && git update-index --add d &&
while test $i -le 100
do
iii=$(printf '%03i' $i)
- test-genrandom "bar" 200 > wide_delta_$iii &&
- test-genrandom "baz $iii" 50 >> wide_delta_$iii &&
- test-genrandom "foo"$i 100 > deep_delta_$iii &&
- test-genrandom "foo"$(expr $i + 1) 100 >> deep_delta_$iii &&
- test-genrandom "foo"$(expr $i + 2) 100 >> deep_delta_$iii &&
+ test-tool genrandom "bar" 200 > wide_delta_$iii &&
+ test-tool genrandom "baz $iii" 50 >> wide_delta_$iii &&
+ test-tool genrandom "foo"$i 100 > deep_delta_$iii &&
+ test-tool genrandom "foo"$(expr $i + 1) 100 >> deep_delta_$iii &&
+ test-tool genrandom "foo"$(expr $i + 2) 100 >> deep_delta_$iii &&
echo $iii >file_$iii &&
- test-genrandom "$iii" 8192 >>file_$iii &&
+ test-tool genrandom "$iii" 8192 >>file_$iii &&
git update-index --add file_$iii deep_delta_$iii wide_delta_$iii &&
i=$(expr $i + 1) || return 1
done &&
- { echo 101 && test-genrandom 100 8192; } >file_101 &&
+ { echo 101 && test-tool genrandom 100 8192; } >file_101 &&
git update-index --add file_101 &&
tree=$(git write-tree) &&
commit=$(git commit-tree $tree </dev/null) && {
# 3) object header is always 2 bytes.
create_test_files() {
- test-genrandom "foo" 2000 > file_1 &&
- test-genrandom "foo" 1800 > file_2 &&
- test-genrandom "foo" 1800 > file_3 &&
+ test-tool genrandom "foo" 2000 > file_1 &&
+ test-tool genrandom "foo" 1800 > file_2 &&
+ test-tool genrandom "foo" 1800 > file_3 &&
echo " base " >> file_1 &&
echo " delta1 " >> file_2 &&
echo " delta delta2 " >> file_3 &&
- test-genrandom "bar" 150 >> file_2 &&
- test-genrandom "baz" 100 >> file_3
+ test-tool genrandom "bar" 150 >> file_2 &&
+ test-tool genrandom "baz" 100 >> file_3
}
create_new_pack() {
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
- test-chmtime =+0 $BLOB_FILE
+ test-tool chmtime =+0 $BLOB_FILE
}
test_expect_success setup '
orig_pack=$(echo .git/objects/pack/*.pack) &&
: > .git/objects/tmp_1.pack &&
: > .git/objects/tmp_2.pack &&
- test-chmtime =-86501 .git/objects/tmp_1.pack &&
+ test-tool chmtime =-86501 .git/objects/tmp_1.pack &&
git prune --expire 1.day &&
test_path_is_file $orig_pack &&
test_path_is_file .git/objects/tmp_2.pack &&
git prune --expire=1.hour.ago &&
verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
- test-chmtime =-86500 $BLOB_FILE &&
+ test-tool chmtime =-86500 $BLOB_FILE &&
git prune --expire 1.day &&
verbose test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
test_expect_success 'gc: implicit prune --expire' '
add_blob &&
- test-chmtime =-$((2*$week-30)) $BLOB_FILE &&
+ test-tool chmtime =-$((2*$week-30)) $BLOB_FILE &&
git gc &&
verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
- test-chmtime =-$((2*$week+1)) $BLOB_FILE &&
+ test-tool chmtime =-$((2*$week+1)) $BLOB_FILE &&
git gc &&
verbose test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
test_expect_success 'gc --no-prune' '
add_blob &&
- test-chmtime =-$((5001*$day)) $BLOB_FILE &&
+ test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
git config gc.pruneExpire 2.days.ago &&
git gc --no-prune &&
verbose test 1 = $(git count-objects | sed "s/ .*//") &&
test_expect_success 'gc --prune=<date>' '
add_blob &&
- test-chmtime =-$((5001*$day)) $BLOB_FILE &&
+ test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
git gc --prune=5002.days.ago &&
test_path_is_file $BLOB_FILE &&
git gc --prune=5000.days.ago &&
test_expect_success 'gc: prune old objects after local clone' '
add_blob &&
- test-chmtime =-$((2*$week+1)) $BLOB_FILE &&
+ test-tool chmtime =-$((2*$week+1)) $BLOB_FILE &&
git clone --no-hardlinks . aclone &&
(
cd aclone &&
'
test_expect_success 'splitting packs does not generate bogus bitmaps' '
- test-genrandom foo $((1024 * 1024)) >rand &&
+ test-tool genrandom foo $((1024 * 1024)) >rand &&
git add rand &&
git commit -m "commit with big file" &&
git -c pack.packSizeLimit=500k repack -adb &&
test_expect_success 'bogus OFS_DELTA in packfile' '
# Generate a pack with a delta in it.
- base=$(test-genrandom foo 3000 | git hash-object --stdin -w) &&
- delta=$(test-genrandom foo 2000 | git hash-object --stdin -w) &&
+ base=$(test-tool genrandom foo 3000 | git hash-object --stdin -w) &&
+ delta=$(test-tool genrandom foo 2000 | git hash-object --stdin -w) &&
do_pack "$base $delta" --delta-base-offset &&
rm -f .git/objects/??/* &&
}
test_expect_success 'setup' '
- test-genrandom base 4096 >base &&
+ test-tool genrandom base 4096 >base &&
for i in one two
do
# we want shared content here to encourage deltas...
# repeatedly-modified file to generate the delta chain).
test_expect_success 'create series of packs' '
- test-genrandom foo 4096 >content &&
+ test-tool genrandom foo 4096 >content &&
prev= &&
for i in $(test_seq 1 10)
do
# And create a file that follows the temporary object naming
# convention for the auto-gc to remove
: >.git/objects/tmp_test_object &&
- test-chmtime =-1209601 .git/objects/tmp_test_object
+ test-tool chmtime =-1209601 .git/objects/tmp_test_object
) &&
(
cd parent &&
test_commit looooooooooooong-tag &&
(
cd full-output &&
- git -c fetch.output=full fetch origin 2>&1 | \
- grep -e "->" | cut -c 22- >../actual
+ git -c fetch.output=full fetch origin >actual 2>&1 &&
+ grep -e "->" actual | cut -c 22- >../actual
) &&
cat >expect <<-\EOF &&
master -> origin/master
test_commit extraaa &&
(
cd compact &&
- git -c fetch.output=compact fetch origin 2>&1 | \
- grep -e "->" | cut -c 22- >../actual
+ git -c fetch.output=compact fetch origin >actual 2>&1 &&
+ grep -e "->" actual | cut -c 22- >../actual
) &&
cat >expect <<-\EOF &&
master -> origin/*
cd testrepo &&
git reset --hard HEAD^ &&
test $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&
- test-chmtime +100 path1
+ test-tool chmtime +100 path1
) &&
git push testrepo master &&
(
}
test_expect_success "create known-size (1024 bytes) commit" '
- test-genrandom foo 1024 >one-k &&
+ test-tool genrandom foo 1024 >one-k &&
git add one-k &&
test_commit one-k
'
# so make it likely for us to generate a delta by having
# a non-trivial file with multiple versions.
- test-genrandom foo 4096 >file.bin &&
+ test-tool genrandom foo 4096 >file.bin &&
git add file.bin &&
git commit -m bin &&
do
printf "Generating blob $i/$blobcount\r" >&2 &&
printf "blob\nmark :$i\ndata $blobsize\n" &&
- #test-genrandom $i $blobsize &&
+ #test-tool genrandom $i $blobsize &&
printf "%-${blobsize}s" $i &&
echo "M 100644 :$i $i" >> commit
i=$(($i+1)) ||
test_expect_success 'avoid unnecessary update, normal rename' '
git checkout -q avoid-unnecessary-update-1^0 &&
- test-chmtime =1000000000 rename &&
- test-chmtime -v +0 rename >expect &&
+ test-tool chmtime =1000000000 rename &&
+ test-tool chmtime -v +0 rename >expect &&
git merge merge-branch-1 &&
- test-chmtime -v +0 rename >actual &&
+ test-tool chmtime -v +0 rename >actual &&
test_cmp expect actual # "rename" should have stayed intact
'
test_expect_success 'avoid unnecessary update, with D/F conflict' '
git checkout -q avoid-unnecessary-update-2^0 &&
- test-chmtime =1000000000 df &&
- test-chmtime -v +0 df >expect &&
+ test-tool chmtime =1000000000 df &&
+ test-tool chmtime -v +0 df >expect &&
git merge merge-branch-2 &&
- test-chmtime -v +0 df >actual &&
+ test-tool chmtime -v +0 df >actual &&
test_cmp expect actual # "df" should have stayed intact
'
test_expect_success 'avoid unnecessary update, dir->(file,nothing)' '
git checkout -q master^0 &&
- test-chmtime =1000000000 df &&
- test-chmtime -v +0 df >expect &&
+ test-tool chmtime =1000000000 df &&
+ test-tool chmtime -v +0 df >expect &&
git merge side &&
- test-chmtime -v +0 df >actual &&
+ test-tool chmtime -v +0 df >actual &&
test_cmp expect actual # "df" should have stayed intact
'
test_expect_success 'avoid unnecessary update, modify/delete' '
git checkout -q master^0 &&
- test-chmtime =1000000000 file &&
- test-chmtime -v +0 file >expect &&
+ test-tool chmtime =1000000000 file &&
+ test-tool chmtime -v +0 file >expect &&
test_must_fail git merge side &&
- test-chmtime -v +0 file >actual &&
+ test-tool chmtime -v +0 file >actual &&
test_cmp expect actual # "file" should have stayed intact
'
test_expect_success 'avoid unnecessary update, rename/add-dest' '
git checkout -q master^0 &&
- test-chmtime =1000000000 newfile &&
- test-chmtime -v +0 newfile >expect &&
+ test-tool chmtime =1000000000 newfile &&
+ test-tool chmtime -v +0 newfile >expect &&
git merge side &&
- test-chmtime -v +0 newfile >actual &&
+ test-tool chmtime -v +0 newfile >actual &&
test_cmp expect actual # "file" should have stayed intact
'
test_must_fail git gc --auto 2>err &&
test_i18ngrep "^error:" err &&
test_config gc.logexpiry 5.days &&
- test-chmtime =-345600 .git/gc.log &&
+ test-tool chmtime =-345600 .git/gc.log &&
test_must_fail git gc --auto &&
test_config gc.logexpiry 2.days &&
run_and_wait_for_auto_gc &&
test_expect_success "simulate time passing ($title)" '
find .git/objects -type f |
- xargs test-chmtime -v -86400
+ xargs test-tool chmtime -v -86400
'
test_expect_success "start writing new commit with old blob ($title)" '
test_expect_success "abandon objects again ($title)" '
git reset --hard HEAD^ &&
find .git/objects -type f |
- xargs test-chmtime -v -86400
+ xargs test-tool chmtime -v -86400
'
test_expect_success "start writing new commit with same tree ($title)" '
test_expect_success \
'checking the commit' \
- 'git diff-tree -r -M --name-status HEAD^ HEAD | \
- grep "^R100..*path0/COPYING..*path1/COPYING"'
+ 'git diff-tree -r -M --name-status HEAD^ HEAD >actual &&
+ grep "^R100..*path0/COPYING..*path1/COPYING" actual'
test_expect_success \
'moving the file back into subdirectory' \
test_expect_success \
'checking the commit' \
- 'git diff-tree -r -M --name-status HEAD^ HEAD | \
- grep "^R100..*path1/COPYING..*path0/COPYING"'
+ 'git diff-tree -r -M --name-status HEAD^ HEAD >actual &&
+ grep "^R100..*path1/COPYING..*path0/COPYING" actual'
test_expect_success \
'mv --dry-run does not move file' \
test_expect_success \
'checking the commit' \
- 'git diff-tree -r -M --name-status HEAD^ HEAD | \
- grep "^R100..*path0/COPYING..*path2/COPYING" &&
- git diff-tree -r -M --name-status HEAD^ HEAD | \
- grep "^R100..*path0/README..*path2/README"'
+ 'git diff-tree -r -M --name-status HEAD^ HEAD >actual &&
+ grep "^R100..*path0/COPYING..*path2/COPYING" actual &&
+ grep "^R100..*path0/README..*path2/README" actual'
test_expect_success \
'succeed when source is a prefix of destination' \
test_expect_success \
'checking the commit' \
- 'git diff-tree -r -M --name-status HEAD^ HEAD | \
- grep "^R100..*path2/COPYING..*path1/path2/COPYING" &&
- git diff-tree -r -M --name-status HEAD^ HEAD | \
- grep "^R100..*path2/README..*path1/path2/README"'
+ 'git diff-tree -r -M --name-status HEAD^ HEAD >actual &&
+ grep "^R100..*path2/COPYING..*path1/path2/COPYING" actual &&
+ grep "^R100..*path2/README..*path1/path2/README" actual'
test_expect_success \
'do not move directory over existing directory' \
test \$GIT_COMMIT != $(git rev-parse master) || \
echo Hallo" \
preserved-author) &&
- test 1 = $(git rev-list --author="B V Uips" preserved-author | wc -l)
+ git rev-list --author="B V Uips" preserved-author >actual &&
+ test_line_count = 1 actual
'
test_expect_success "remove a certain author's commits" '
cnt1=$(git rev-list master | wc -l) &&
cnt2=$(git rev-list removed-author | wc -l) &&
test $cnt1 -eq $(($cnt2 + 1)) &&
- test 0 = $(git rev-list --author="B V Uips" removed-author | wc -l)
+ git rev-list --author="B V Uips" removed-author >actual &&
+ test_line_count = 0 actual
'
test_expect_success 'barf on invalid name' '
git commit -m "Re-adding foo" &&
git filter-branch -f --subdirectory-filter foo &&
- test $(git rev-list master | wc -l) = 3
+ git rev-list master >actual &&
+ test_line_count = 3 actual
'
test_expect_success 'Tag name filtering retains tag message' '
git show HEAD:$ambiguous
'
+test_expect_success 'rewrite repository including refs that point at non-commit object' '
+ test_when_finished "git reset --hard original" &&
+ tree=$(git rev-parse HEAD^{tree}) &&
+ test_when_finished "git replace -d $tree" &&
+ echo A >new &&
+ git add new &&
+ new_tree=$(git write-tree) &&
+ git replace $tree $new_tree &&
+ git tag -a -m "tag to a tree" treetag $new_tree &&
+ git reset --hard HEAD &&
+ git filter-branch -f -- --all >filter-output 2>&1 &&
+ ! fgrep fatal filter-output
+'
+
test_done
)
'
+test_expect_success 'moving the submodule does not break the superproject' '
+ (
+ cd addtest2 &&
+ git submodule status
+ ) >actual &&
+ sed -e "s/^ \([^ ]* repo\) .*/-\1/" <actual >expect &&
+ mv addtest2/repo addtest2/repo.bak &&
+ test_when_finished "mv addtest2/repo.bak addtest2/repo" &&
+ (
+ cd addtest2 &&
+ git submodule status
+ ) >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'submodule add --name allows to replace a submodule with another at the same path' '
(
cd addtest2 &&
EOF
(
cd repo &&
- test_must_fail test-submodule-config "" s 2>actual &&
+ test_must_fail test-tool submodule-config "" s 2>actual &&
test_i18ngrep "bad config" actual
)
'
test_expect_success 'test parsing and lookup of submodule config by path' '
(cd super &&
- test-submodule-config \
+ test-tool submodule-config \
HEAD^ a \
HEAD b \
HEAD^ submodule \
test_expect_success 'test parsing and lookup of submodule config by name' '
(cd super &&
- test-submodule-config --name \
+ test-tool submodule-config --name \
HEAD^ a \
HEAD a \
HEAD^ submodule \
git add .gitmodules &&
mv .gitmodules.bak .gitmodules &&
git commit -m "add error" &&
- test-submodule-config \
+ test-tool submodule-config \
HEAD b \
HEAD submodule \
>actual &&
test_expect_success 'error message contains blob reference' '
(cd super &&
sha1=$(git rev-parse HEAD) &&
- test-submodule-config \
+ test-tool submodule-config \
HEAD b \
HEAD submodule \
2>actual_err &&
git tag new_tag &&
tree=$(git rev-parse HEAD^{tree}) &&
commit=$(git rev-parse HEAD^{commit}) &&
- test-submodule-config $commit b >expect &&
- test-submodule-config $tree b >actual.1 &&
- test-submodule-config new_tag b >actual.2 &&
+ test-tool submodule-config $commit b >expect &&
+ test-tool submodule-config $tree b >actual.1 &&
+ test-tool submodule-config new_tag b >actual.2 &&
test_cmp expect actual.1 &&
test_cmp expect actual.2
)
git config --unset -f .gitmodules \
submodule.submodule.fetchrecursesubmodules &&
git commit -m "add error in fetchrecursesubmodules" &&
- test-submodule-config \
+ test-tool submodule-config \
HEAD b \
HEAD submodule \
>actual &&
'
test_expect_success '--no-optional-locks prevents index update' '
- test-chmtime =1234567890 .git/index &&
+ test-tool chmtime =1234567890 .git/index &&
git --no-optional-locks status &&
- test-chmtime -v +0 .git/index >out &&
+ test-tool chmtime -v +0 .git/index >out &&
grep ^1234567890 out &&
git status &&
- test-chmtime -v +0 .git/index >out &&
+ test-tool chmtime -v +0 .git/index >out &&
! grep ^1234567890 out
'
tmppack=".git/objects/pack/tmp_pack" &&
ln "$packfile" "$tmppack" &&
git repack -A -l -d &&
- test-chmtime -v +0 "$tmppack" "$fsha1path" "$csha1path" "$tsha1path" \
+ test-tool chmtime -v +0 "$tmppack" "$fsha1path" "$csha1path" "$tsha1path" \
> mtimes &&
compare_mtimes < mtimes
'
git prune-packed &&
git cat-file -p $obj1 &&
git cat-file -p $obj2 &&
- test-chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&
+ test-tool chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&
git repack -A -d --unpack-unreachable=1.hour.ago &&
git cat-file -p $obj1 &&
test_must_fail git cat-file -p $obj2
git reset HEAD^ &&
git reflog expire --expire=now --all &&
git add file &&
- test-chmtime =-86400 .git/objects/pack/* &&
+ test-tool chmtime =-86400 .git/objects/pack/* &&
git gc --prune=1.hour.ago &&
git cat-file blob :file
'
'
test_have_prereq GETTEXT_LOCALE &&
-test-regex "HALLÓ" "Halló" ICASE &&
+test-tool regex "HALLÓ" "Halló" ICASE &&
test_set_prereq REGEX_LOCALE
test_expect_success REGEX_LOCALE 'grep literal string, no -F' '
. ./test-lib.sh
test_expect_success 'decorate' '
- test-example-decorate
+ test-tool example-decorate
'
test_done
test_expect_success 'dcommit should not fail with a touched file' '
test_commit "commit-new-file-foo2" foo2 &&
- test-chmtime =-60 foo &&
+ test-tool chmtime =-60 foo &&
git svn dcommit
'
test_expect_success 'rebase should not fail with a touched file' '
- test-chmtime =-60 foo &&
+ test-tool chmtime =-60 foo &&
git svn rebase
'
git svn fetch -i thunk &&
test "$(git rev-parse --verify refs/remotes/thunk@2)" \
= "$(git rev-parse --verify refs/remotes/thunk~1)" &&
- test "$(git cat-file blob refs/remotes/thunk:readme |\
- sed -n -e "3p")" = goodbye &&
+ git cat-file blob refs/remotes/thunk:readme >actual &&
+ test "$(sed -n -e "3p" actual)" = goodbye &&
test -z "$(git config --get svn-remote.svn.fetch \
"^trunk:refs/remotes/thunk@2$")"
'
git svn fetch -i svn/thunk &&
test "$(git rev-parse --verify refs/remotes/svn/trunk)" \
= "$(git rev-parse --verify refs/remotes/svn/thunk~1)" &&
- test "$(git cat-file blob refs/remotes/svn/thunk:readme |\
- sed -n -e "3p")" = goodbye
+ git cat-file blob refs/remotes/svn/thunk:readme >actual &&
+ test "$(sed -n -e "3p" actual)" = goodbye
'
test_expect_success 'follow deleted parent' '
git svn init --minimize-url -i glob "$svnrepo"/glob &&
git svn fetch -i glob &&
test "$(git cat-file blob refs/remotes/glob:blob/bye)" = hi &&
- test "$(git ls-tree refs/remotes/glob | wc -l )" -eq 1
+ git ls-tree refs/remotes/glob >actual &&
+ test_line_count = 1 actual
'
# ref: r9270 of the Subversion repository: (http://svn.collab.net/repos/svn)
test_expect_success "track multi-parent paths" '
svn_cmd cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
git svn multi-fetch &&
- test $(git cat-file commit refs/remotes/glob | \
- grep "^parent " | wc -l) -eq 2
+ git cat-file commit refs/remotes/glob >actual &&
+ grep "^parent " actual >actual2 &&
+ test_line_count = 2 actual2
'
test_expect_success "multi-fetch continues to work" "
git config --add svn-remote.svn.tags\
"tags/*/src/a:refs/remotes/tags/*" &&
git svn multi-fetch &&
- git log --pretty=oneline refs/remotes/tags/end | \
- sed -e "s/^.\{41\}//" > output.end &&
+ git log --pretty=oneline refs/remotes/tags/end >actual &&
+ sed -e "s/^.\{41\}//" actual >output.end &&
test_cmp expect.end output.end &&
test "$(git rev-parse refs/remotes/tags/end~1)" = \
"$(git rev-parse refs/remotes/branches/start)" &&
svn_cmd commit -m "try to try"
) &&
git svn fetch two &&
- test $(git rev-list refs/remotes/two/tags/end | wc -l) -eq 6 &&
- test $(git rev-list refs/remotes/two/branches/start | wc -l) -eq 3 &&
+ git rev-list refs/remotes/two/tags/end >actual &&
+ test_line_count = 6 actual &&
+ git rev-list refs/remotes/two/branches/start >actual &&
+ test_line_count = 3 actual &&
test $(git rev-parse refs/remotes/two/branches/start~2) = \
$(git rev-parse refs/remotes/two/trunk) &&
test $(git rev-parse refs/remotes/two/tags/end~3) = \
$(git rev-parse refs/remotes/two/branches/start) &&
- git log --pretty=oneline refs/remotes/two/tags/end | \
- sed -e "s/^.\{41\}//" > output.two &&
+ git log --pretty=oneline refs/remotes/two/tags/end >actual &&
+ sed -e "s/^.\{41\}//" actual >output.two &&
test_cmp expect.two output.two
'
git config --add svn-remote.svn.tags\
"tags/*/src/a:refs/remotes/tags/*" &&
git svn multi-fetch &&
- git log --pretty=oneline refs/remotes/tags/end | \
- sed -e "s/^.\{41\}//" > output.end &&
+ git log --pretty=oneline refs/remotes/tags/end >actual &&
+ sed -e "s/^.\{41\}//" actual >output.end &&
test_cmp expect.end output.end &&
test "$(git rev-parse refs/remotes/tags/end~1)" = \
"$(git rev-parse refs/remotes/branches/v1/start)" &&
svn_cmd commit -m "try to try"
) &&
git svn fetch two &&
- test $(git rev-list refs/remotes/two/tags/end | wc -l) -eq 6 &&
- test $(git rev-list refs/remotes/two/branches/v1/start | wc -l) -eq 3 &&
+ git rev-list refs/remotes/two/tags/end >actual &&
+ test_line_count = 6 actual &&
+ git rev-list refs/remotes/two/branches/v1/start >actual &&
+ test_line_count = 3 actual &&
test $(git rev-parse refs/remotes/two/branches/v1/start~2) = \
$(git rev-parse refs/remotes/two/trunk) &&
test $(git rev-parse refs/remotes/two/tags/end~3) = \
$(git rev-parse refs/remotes/two/branches/v1/start) &&
- git log --pretty=oneline refs/remotes/two/tags/end | \
- sed -e "s/^.\{41\}//" > output.two &&
+ git log --pretty=oneline refs/remotes/two/tags/end >actual &&
+ sed -e "s/^.\{41\}//" actual >output.two &&
test_cmp expect.two output.two
'
cat > expect.four <<EOF
git config --add svn-remote.four.tags \
"tags/*:refs/remotes/four/tags/*" &&
git svn fetch four &&
- test $(git rev-list refs/remotes/four/tags/next | wc -l) -eq 5 &&
- test $(git rev-list refs/remotes/four/branches/v2/start | wc -l) -eq 3 &&
+ git rev-list refs/remotes/four/tags/next >actual &&
+ test_line_count = 5 actual &&
+ git rev-list refs/remotes/four/branches/v2/start >actual &&
+ test_line_count = 3 actual &&
test $(git rev-parse refs/remotes/four/branches/v2/start~2) = \
$(git rev-parse refs/remotes/four/trunk) &&
test $(git rev-parse refs/remotes/four/tags/next~2) = \
$(git rev-parse refs/remotes/four/branches/v2/start) &&
- git log --pretty=oneline refs/remotes/four/tags/next | \
- sed -e "s/^.\{41\}//" > output.four &&
+ git log --pretty=oneline refs/remotes/four/tags/next >actual &&
+ sed -e "s/^.\{41\}//" actual >output.four &&
test_cmp expect.four output.four
'
bar_url=http://mayonaise/svnrepo/bar
test_expect_success 'verify metadata for /bar' "
- git cat-file commit refs/remotes/bar | \
- grep '^git-svn-id: $bar_url@12 $uuid$' &&
- git cat-file commit refs/remotes/bar~1 | \
- grep '^git-svn-id: $bar_url@11 $uuid$' &&
- git cat-file commit refs/remotes/bar~2 | \
- grep '^git-svn-id: $bar_url@10 $uuid$' &&
- git cat-file commit refs/remotes/bar~3 | \
- grep '^git-svn-id: $bar_url@9 $uuid$' &&
- git cat-file commit refs/remotes/bar~4 | \
- grep '^git-svn-id: $bar_url@6 $uuid$' &&
- git cat-file commit refs/remotes/bar~5 | \
- grep '^git-svn-id: $bar_url@1 $uuid$'
+ git cat-file commit refs/remotes/bar >actual &&
+ grep '^git-svn-id: $bar_url@12 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~1 >actual &&
+ grep '^git-svn-id: $bar_url@11 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~2 >actual &&
+ grep '^git-svn-id: $bar_url@10 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~3 >actual &&
+ grep '^git-svn-id: $bar_url@9 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~4 >actual &&
+ grep '^git-svn-id: $bar_url@6 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~5 >actual &&
+ grep '^git-svn-id: $bar_url@1 $uuid$' actual
"
e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e
test_expect_success 'verify metadata for /dir/a/b/c/d/e' "
- git cat-file commit refs/remotes/e | \
- grep '^git-svn-id: $e_url@1 $uuid$'
+ git cat-file commit refs/remotes/e >actual &&
+ grep '^git-svn-id: $e_url@1 $uuid$' actual
"
dir_url=http://mayonaise/svnrepo/dir
test_expect_success 'verify metadata for /dir' "
- git cat-file commit refs/remotes/dir | \
- grep '^git-svn-id: $dir_url@2 $uuid$' &&
- git cat-file commit refs/remotes/dir~1 | \
- grep '^git-svn-id: $dir_url@1 $uuid$'
+ git cat-file commit refs/remotes/dir >actual &&
+ grep '^git-svn-id: $dir_url@2 $uuid$' actual &&
+ git cat-file commit refs/remotes/dir~1 >actual &&
+ grep '^git-svn-id: $dir_url@1 $uuid$' actual
"
test_expect_success 'find commit based on SVN revision number' "
- git svn find-rev r12 |
- grep $(git rev-parse HEAD)
+ git svn find-rev r12 >actual &&
+ grep $(git rev-parse HEAD) actual
"
test_expect_success 'empty rebase' "
bar_url=http://mayonaise/svnrepo/bar
test_expect_success 'verify metadata for /bar' "
- git cat-file commit refs/remotes/bar | \
- grep '^git-svn-id: $bar_url@12 $uuid$' &&
- git cat-file commit refs/remotes/bar~1 | \
- grep '^git-svn-id: $bar_url@11 $uuid$' &&
- git cat-file commit refs/remotes/bar~2 | \
- grep '^git-svn-id: $bar_url@10 $uuid$' &&
- git cat-file commit refs/remotes/bar~3 | \
- grep '^git-svn-id: $bar_url@9 $uuid$' &&
- git cat-file commit refs/remotes/bar~4 | \
- grep '^git-svn-id: $bar_url@6 $uuid$' &&
- git cat-file commit refs/remotes/bar~5 | \
- grep '^git-svn-id: $bar_url@1 $uuid$'
+ git cat-file commit refs/remotes/bar >actual &&
+ grep '^git-svn-id: $bar_url@12 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~1 >actual &&
+ grep '^git-svn-id: $bar_url@11 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~2 >actual &&
+ grep '^git-svn-id: $bar_url@10 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~3 >actual &&
+ grep '^git-svn-id: $bar_url@9 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~4 >actual &&
+ grep '^git-svn-id: $bar_url@6 $uuid$' actual &&
+ git cat-file commit refs/remotes/bar~5 >actual &&
+ grep '^git-svn-id: $bar_url@1 $uuid$' actual
"
e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e
test_expect_success 'verify metadata for /dir/a/b/c/d/e' "
- git cat-file commit refs/remotes/e | \
- grep '^git-svn-id: $e_url@1 $uuid$'
+ git cat-file commit refs/remotes/e >actual &&
+ grep '^git-svn-id: $e_url@1 $uuid$' actual
"
dir_url=http://mayonaise/svnrepo/dir
test_expect_success 'verify metadata for /dir' "
- git cat-file commit refs/remotes/dir | \
- grep '^git-svn-id: $dir_url@2 $uuid$' &&
- git cat-file commit refs/remotes/dir~1 | \
- grep '^git-svn-id: $dir_url@1 $uuid$'
+ git cat-file commit refs/remotes/dir >actual &&
+ grep '^git-svn-id: $dir_url@2 $uuid$' actual &&
+ git cat-file commit refs/remotes/dir~1 >actual &&
+ grep '^git-svn-id: $dir_url@1 $uuid$' actual
"
test_done
test_expect_success 'verify pre-merge ancestry' "
test x\$(git rev-parse --verify refs/heads/svn^2) = \
x\$(git rev-parse --verify refs/heads/merge) &&
- git cat-file commit refs/heads/svn^ | grep '^friend$'
+ git cat-file commit refs/heads/svn^ >actual &&
+ grep '^friend$' actual
"
test_expect_success 'git svn dcommit merges' "
x\$(git rev-parse --verify refs/remotes/origin/trunk) &&
test x\$(git rev-parse --verify refs/heads/svn^2) = \
x\$(git rev-parse --verify refs/heads/merge) &&
- git cat-file commit refs/heads/svn^ | grep '^friend$'
+ git cat-file commit refs/heads/svn^ >actual &&
+ grep '^friend$' actual
"
test_expect_success 'verify merge commit message' "
- git rev-list --pretty=raw -1 refs/heads/svn | \
- grep \" Merge branch 'merge' into svn\"
+ git rev-list --pretty=raw -1 refs/heads/svn >actual &&
+ grep \" Merge branch 'merge' into svn\" actual
"
test_done
test_expect_success 'imported 2 revisions successfully' '
(
cd x
- test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 2 &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn | \
- grep "^author BBBBBBB BBBBBBB <bb@example\.com> " &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
- grep "^author AAAAAAA AAAAAAA <aa@example\.com> "
+ git rev-list refs/remotes/git-svn >actual &&
+ test_line_count = 2 actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn >actual &&
+ grep "^author BBBBBBB BBBBBBB <bb@example\.com> " actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 >actual &&
+ grep "^author AAAAAAA AAAAAAA <aa@example\.com> " actual
)
'
(
cd x
git svn fetch --authors-file=../svn-authors &&
- test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 4 &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn | \
- grep "^author DDDDDDD DDDDDDD <dd@example\.com> " &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
- grep "^author CCCCCCC CCCCCCC <cc@example\.com> "
+ git rev-list refs/remotes/git-svn >actual &&
+ test_line_count = 4 actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn >actual &&
+ grep "^author DDDDDDD DDDDDDD <dd@example\.com> " actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 >actual &&
+ grep "^author CCCCCCC CCCCCCC <cc@example\.com> " actual
)
'
test x"$HOME"/svn-authors = x"$(git config svn.authorsfile)" &&
git svn clone "$svnrepo" gitconfig.clone &&
cd gitconfig.clone &&
- nr_ex=$(git log | grep "^Author:.*example.com" | wc -l) &&
- nr_rev=$(git rev-list HEAD | wc -l) &&
+ git log >actual &&
+ nr_ex=$(grep "^Author:.*example.com" actual | wc -l) &&
+ git rev-list HEAD >actual &&
+ nr_rev=$(wc -l <actual) &&
test $nr_rev -eq $nr_ex
)
'
test_expect_success 'imported 6 revisions successfully' '
(
cd x
- test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 6
+ git rev-list refs/remotes/git-svn >actual &&
+ test_line_count = 6 actual
)
'
test_expect_success 'authors-prog ran correctly' '
(
cd x
- git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
- grep "^author ee-foo <ee-foo@example\.com> " &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn~2 | \
- grep "^author dd <dd@sub\.example\.com> " &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn~3 | \
- grep "^author cc <cc@sub\.example\.com> " &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn~4 | \
- grep "^author bb <bb@example\.com> " &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn~5 | \
- grep "^author aa <aa@example\.com> "
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 >actual &&
+ grep "^author ee-foo <ee-foo@example\.com> " actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~2 >actual &&
+ grep "^author dd <dd@sub\.example\.com> " actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~3 >actual &&
+ grep "^author cc <cc@sub\.example\.com> " actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~4 >actual &&
+ grep "^author bb <bb@example\.com> " actual &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~5 >actual &&
+ grep "^author aa <aa@example\.com> " actual
)
'
test_expect_success 'authors-file overrode authors-prog' '
(
cd x
- git rev-list -1 --pretty=raw refs/remotes/git-svn | \
- grep "^author FFFFFFF FFFFFFF <fFf@other\.example\.com> "
+ git rev-list -1 --pretty=raw refs/remotes/git-svn >actual &&
+ grep "^author FFFFFFF FFFFFFF <fFf@other\.example\.com> " actual
)
'
(
cd x &&
git svn --authors-prog=../svn-authors-prog fetch &&
- git rev-list -1 --pretty=raw refs/remotes/git-svn |
- grep "^author xyz; touch evil <xyz; touch evil@example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn >actual &&
+ grep "^author xyz; touch evil <xyz; touch evil@example\.com> " actual &&
! test -f evil
)
'
"
test_expect_success 'verify uuid' "
- git cat-file commit refs/remotes/git-svn~0 | \
- grep '^git-svn-id: .*@2 $uuid$' &&
- git cat-file commit refs/remotes/git-svn~1 | \
- grep '^git-svn-id: .*@1 $uuid$'
+ git cat-file commit refs/remotes/git-svn~0 >actual &&
+ grep '^git-svn-id: .*@2 $uuid$' actual &&
+ git cat-file commit refs/remotes/git-svn~1 >actual &&
+ grep '^git-svn-id: .*@1 $uuid$' actual
"
test_done
git config --add svn-remote.svn.tags\
"tags/t_*/src/a:refs/remotes/tags/t_*" &&
git svn multi-fetch &&
- git log --pretty=oneline refs/remotes/tags/t_end | \
- sed -e "s/^.\{41\}//" >output.end &&
+ git log --pretty=oneline refs/remotes/tags/t_end >actual &&
+ sed -e "s/^.\{41\}//" actual >output.end &&
test_cmp expect.end output.end &&
test "$(git rev-parse refs/remotes/tags/t_end~1)" = \
"$(git rev-parse refs/remotes/branches/b_start)" &&
svn_cmd commit -m "try to try"
) &&
git svn fetch two &&
- test $(git rev-list refs/remotes/two/tags/t_end | wc -l) -eq 6 &&
- test $(git rev-list refs/remotes/two/branches/b_start | wc -l) -eq 3 &&
+ git rev-list refs/remotes/two/tags/t_end >actual &&
+ test_line_count = 6 actual &&
+ git rev-list refs/remotes/two/branches/b_start >actual &&
+ test_line_count = 3 actual &&
test $(git rev-parse refs/remotes/two/branches/b_start~2) = \
$(git rev-parse refs/remotes/two/trunk) &&
test $(git rev-parse refs/remotes/two/tags/t_end~3) = \
$(git rev-parse refs/remotes/two/branches/b_start) &&
- git log --pretty=oneline refs/remotes/two/tags/t_end | \
- sed -e "s/^.\{41\}//" >output.two &&
+ git log --pretty=oneline refs/remotes/two/tags/t_end >actual &&
+ sed -e "s/^.\{41\}//" actual >output.two &&
test_cmp expect.two output.two
'
svn_cmd up
) &&
git svn fetch three &&
- test $(git rev-list refs/remotes/three/branches/b_ | wc -l) -eq 2 &&
- test $(git rev-list refs/remotes/three/tags/t_ | wc -l) -eq 3 &&
+ git rev-list refs/remotes/three/branches/b_ >actual &&
+ test_line_count = 2 actual &&
+ git rev-list refs/remotes/three/tags/t_ >actual &&
+ test_line_count = 3 actual &&
test $(git rev-parse refs/remotes/three/branches/b_~1) = \
$(git rev-parse refs/remotes/three/trunk) &&
test $(git rev-parse refs/remotes/three/tags/t_~1) = \
$(git rev-parse refs/remotes/three/branches/b_) &&
- git log --pretty=oneline refs/remotes/three/tags/t_ | \
- sed -e "s/^.\{41\}//" >output.three &&
+ git log --pretty=oneline refs/remotes/three/tags/t_ >actual &&
+ sed -e "s/^.\{41\}//" actual >output.three &&
test_cmp expect.three output.three
'
svn_cmd up
) &&
git svn fetch five &&
- test $(git rev-list refs/remotes/five/branches/abcde | wc -l) -eq 2 &&
- test $(git rev-list refs/remotes/five/tags/fghij | wc -l) -eq 3 &&
+ git rev-list refs/remotes/five/branches/abcde >actual &&
+ test_line_count = 2 actual &&
+ git rev-list refs/remotes/five/tags/fghij >actual &&
+ test_line_count = 3 actual &&
test $(git rev-parse refs/remotes/five/branches/abcde~1) = \
$(git rev-parse refs/remotes/five/trunk) &&
test $(git rev-parse refs/remotes/five/tags/fghij~1) = \
$(git rev-parse refs/remotes/five/branches/abcde) &&
- git log --pretty=oneline refs/remotes/five/tags/fghij | \
- sed -e "s/^.\{41\}//" >output.five &&
+ git log --pretty=oneline refs/remotes/five/tags/fghij >actual &&
+ sed -e "s/^.\{41\}//" actual >output.five &&
test_cmp expect.five output.five
'
##
test_expect_success 'R: blob bigger than threshold' '
blobsize=$((2*1024*1024 + 53)) &&
- test-genrandom bar $blobsize >expect &&
+ test-tool genrandom bar $blobsize >expect &&
cat >input <<-INPUT_END &&
commit refs/heads/big-file
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
MUSS=$(git rev-parse --verify muss) &&
mkdir new &&
git --git-dir=new/.git init &&
- git fast-export --all |
+ git fast-export --all >actual &&
(cd new &&
git fast-import &&
test $MASTER = $(git rev-parse --verify refs/heads/master) &&
test $REIN = $(git rev-parse --verify refs/tags/rein) &&
test $WER = $(git rev-parse --verify refs/heads/wer) &&
- test $MUSS = $(git rev-parse --verify refs/tags/muss))
+ test $MUSS = $(git rev-parse --verify refs/tags/muss)) <actual
'
test_expect_success 'fast-export master~2..master' '
- git fast-export master~2..master |
- sed "s/master/partial/" |
+ git fast-export master~2..master >actual &&
+ sed "s/master/partial/" actual |
(cd new &&
git fast-import &&
test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
test_tick &&
echo rosten >file &&
git commit -s -m den file &&
- git fast-export wer^..wer |
- sed "s/wer/i18n/" |
+ git fast-export wer^..wer >iso8859-1.fi &&
+ sed "s/wer/i18n/" iso8859-1.fi |
(cd new &&
git fast-import &&
- git cat-file commit i18n | grep "Áéí óú")
+ git cat-file commit i18n >actual &&
+ grep "Áéí óú" actual)
'
test_expect_success 'import/export-marks' '
git fast-export --export-marks=tmp-marks HEAD &&
test -s tmp-marks &&
test_line_count = 3 tmp-marks &&
- test $(
- git fast-export --import-marks=tmp-marks\
- --export-marks=tmp-marks HEAD |
- grep ^commit |
- wc -l) \
- -eq 0 &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks HEAD >actual &&
+ test $(grep ^commit actual | wc -l) -eq 0 &&
echo change > file &&
git commit -m "last commit" file &&
- test $(
- git fast-export --import-marks=tmp-marks \
- --export-marks=tmp-marks HEAD |
- grep ^commit\ |
- wc -l) \
- -eq 1 &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks HEAD >actual &&
+ test $(grep ^commit\ actual | wc -l) -eq 1 &&
test_line_count = 4 tmp-marks
'
rm -rf new &&
mkdir new &&
git --git-dir=new/.git init &&
- git fast-export --signed-tags=strip --all |
+ git fast-export --signed-tags=strip --all >actual &&
(cd new &&
git fast-import &&
test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" &&
git checkout master &&
git submodule init &&
git submodule update &&
- cmp sub/file ../sub/file)
+ cmp sub/file ../sub/file) <actual
'
echo more content >> file &&
test_tick &&
git commit -mnext file &&
- git fast-export --import-marks=marks simple -- file file0 | grep file0
+ git fast-export --import-marks=marks simple -- file file0 >actual &&
+ grep file0 actual
'
test_expect_success 'full-tree re-shows unmodified files' '
git checkout -f simple &&
- test $(git fast-export --full-tree simple | grep -c file0) -eq 3
+ git fast-export --full-tree simple >actual &&
+ test $(grep -c file0 actual) -eq 3
'
test_expect_success 'set-up a few more tags for tag export tests' '
'
test_expect_success 'use refspec' '
- git fast-export --refspec refs/heads/master:refs/heads/foobar master | \
- grep "^commit " | sort | uniq > actual &&
+ git fast-export --refspec refs/heads/master:refs/heads/foobar master >actual2 &&
+ grep "^commit " actual2 | sort | uniq >actual &&
echo "commit refs/heads/foobar" > expected &&
test_cmp expected actual
'
git -C src commit -m 2nd_commit &&
test_create_repo dst &&
- git -C src fast-export --all -C | git -C dst fast-import &&
+ git -C src fast-export --all -C >actual &&
+ git -C dst fast-import <actual &&
git -C src show >expected &&
git -C dst show >actual &&
test_cmp expected actual
build_gendouble &&
(
cd "$cli" &&
- test-genrandom apple 1024 >double.png &&
+ test-tool genrandom apple 1024 >double.png &&
"$PYTHON_PATH" "$TRASH_DIRECTORY/gendouble.py" >%double.png &&
p4 add -t apple double.png &&
p4 submit -d appledouble
echo f2 >"file with spaces" &&
git add "file with spaces" &&
git commit -m "add files" &&
- P4EDITOR="test-chmtime +5" git p4 submit
+ P4EDITOR="test-tool chmtime +5" git p4 submit
) &&
(
cd "$cli" &&
git rm foo\$bar &&
git rm file\ with\ spaces &&
git commit -m "remove files" &&
- P4EDITOR="test-chmtime +5" git p4 submit
+ P4EDITOR="test-tool chmtime +5" git p4 submit
) &&
(
cd "$cli" &&
git commit --author "Alice <alice@example.com>" -m "a change by alice" file1 &&
git commit --author "Bob <bob@example.com>" -m "a change by bob" file2 &&
git config git-p4.skipSubmitEditCheck true &&
- P4EDITOR="test-chmtime +5" P4USER=alice P4PASSWD=secret &&
+ P4EDITOR="test-tool chmtime +5" P4USER=alice P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
git p4 commit --preserve-user &&
p4_check_commit_author file1 alice &&
git config git-p4.skipSubmitEditCheck true &&
echo "username-noperms: a change by alice" >>file1 &&
git commit --author "Alice <alice@example.com>" -m "perms: a change by alice" file1 &&
- P4EDITOR="test-chmtime +5" P4USER=bob P4PASSWD=secret &&
+ P4EDITOR="test-tool chmtime +5" P4USER=bob P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
test_must_fail git p4 commit --preserve-user &&
! git diff --exit-code HEAD..p4/master
git commit --author "Bob <bob@example.com>" -m "preserve: a change by bob" file1 &&
echo "username-unknown: a change by charlie" >>file1 &&
git commit --author "Charlie <charlie@example.com>" -m "preserve: a change by charlie" file1 &&
- P4EDITOR="test-chmtime +5" P4USER=alice P4PASSWD=secret &&
+ P4EDITOR="test-tool chmtime +5" P4USER=alice P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
test_must_fail git p4 commit --preserve-user &&
! git diff --exit-code HEAD..p4/master &&
cd "$git" &&
echo change >file1 &&
git commit -m "change" file1 &&
- P4EDITOR=": >\"$git/touched\" && test-chmtime +5" git p4 submit &&
+ P4EDITOR=": >\"$git/touched\" && test-tool chmtime +5" git p4 submit &&
test_path_is_file "$git/touched"
)
'
EOF
'
+test_expect_success 'completion without explicit _git_xxx function' '
+ test_completion "git version --" <<-\EOF
+ --build-options Z
+ EOF
+'
+
test_expect_failure 'complete with tilde expansion' '
git init tmp && cd tmp &&
test_when_finished "cd .. && rm -rf tmp" &&
# otherwise.
test_must_be_empty () {
- if ! test -f "$1"
- then
- echo "'$1' is missing"
- return 1
- elif test -s "$1"
+ test_path_is_file "$1" &&
+ if test -s "$1"
then
echo "'$1' is not empty, it contains:"
cat "$1"
error "You haven't built things yet, have you?"
}
-if ! test -x "$GIT_BUILD_DIR"/t/helper/test-chmtime
+if ! test -x "$GIT_BUILD_DIR"/t/helper/test-tool
then
- echo >&2 'You need to build test-chmtime:'
- echo >&2 'Run "make t/helper/test-chmtime" in the source (toplevel) directory'
+ echo >&2 'You need to build test-tool:'
+ echo >&2 'Run "make t/helper/test-tool" in the source (toplevel) directory'
exit 1
fi
test 8 -le "$(build_option sizeof-long)"
'
-test_lazy_prereq TIME_IS_64BIT 'test-date is64bit'
-test_lazy_prereq TIME_T_IS_64BIT 'test-date time_t-is64bit'
+test_lazy_prereq TIME_IS_64BIT 'test-tool date is64bit'
+test_lazy_prereq TIME_T_IS_64BIT 'test-tool date time_t-is64bit'
unsigned long size;
int ret;
- type = sha1_object_info(oid->hash, NULL);
+ type = oid_object_info(oid, NULL);
if (type != OBJ_TAG)
return error("%s: cannot verify a non-tag object of type %s.",
name_to_report ?
name_to_report :
- find_unique_abbrev(oid->hash, DEFAULT_ABBREV),
+ find_unique_abbrev(oid, DEFAULT_ABBREV),
type_name(type));
- buf = read_sha1_file(oid->hash, &type, &size);
+ buf = read_object_file(oid, &type, &size);
if (!buf)
return error("%s: unable to read file.",
name_to_report ?
name_to_report :
- find_unique_abbrev(oid->hash, DEFAULT_ABBREV));
+ find_unique_abbrev(oid, DEFAULT_ABBREV));
ret = run_gpg_verify(buf, size, flags);
if (item->object.parsed)
return 0;
- data = read_sha1_file(item->object.oid.hash, &type, &size);
+ data = read_object_file(&item->object.oid, &type, &size);
if (!data)
return error("Could not read %s",
oid_to_hex(&item->object.oid));
#include "strbuf.h"
#include "argv-array.h"
#include "quote.h"
+#include "object-store.h"
struct tmp_objdir {
struct strbuf path;
#include "sha1-array.h"
#include "sigchain.h"
#include "transport-internal.h"
+#include "object-store.h"
static void set_upstreams(struct transport *transport, struct ref *refs,
int pretend)
char type;
const char *msg;
- strbuf_add_unique_abbrev(&quickref, ref->old_oid.hash,
+ strbuf_add_unique_abbrev(&quickref, &ref->old_oid,
DEFAULT_ABBREV);
if (ref->forced_update) {
strbuf_addstr(&quickref, "...");
type = ' ';
msg = NULL;
}
- strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash,
+ strbuf_add_unique_abbrev(&quickref, &ref->new_oid,
DEFAULT_ABBREV);
print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg,
static int measure_abbrev(const struct object_id *oid, int sofar)
{
char hex[GIT_MAX_HEXSZ + 1];
- int w = find_unique_abbrev_r(hex, oid->hash, DEFAULT_ABBREV);
+ int w = find_unique_abbrev_r(hex, oid, DEFAULT_ABBREV);
return (w < sofar) ? sofar : w;
}
void *buf = NULL;
if (oid) {
- buf = read_object_with_reference(oid->hash, tree_type, &size,
- NULL);
+ buf = read_object_with_reference(oid, tree_type, &size, NULL);
if (!buf)
die("unable to read tree %s", oid_to_hex(oid));
}
unsigned char sha1[20];
};
-static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode)
+static int find_tree_entry(struct tree_desc *t, const char *name, struct object_id *result, unsigned *mode)
{
int namelen = strlen(name);
while (t->size) {
if (cmp < 0)
break;
if (entrylen == namelen) {
- hashcpy(result, oid->hash);
+ oidcpy(result, oid);
return 0;
}
if (name[entrylen] != '/')
if (!S_ISDIR(*mode))
break;
if (++entrylen == namelen) {
- hashcpy(result, oid->hash);
+ oidcpy(result, oid);
return 0;
}
- return get_tree_entry(oid->hash, name + entrylen, result, mode);
+ return get_tree_entry(oid, name + entrylen, result, mode);
}
return -1;
}
-int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned char *sha1, unsigned *mode)
+int get_tree_entry(const struct object_id *tree_oid, const char *name, struct object_id *oid, unsigned *mode)
{
int retval;
void *tree;
unsigned long size;
- unsigned char root[20];
+ struct object_id root;
- tree = read_object_with_reference(tree_sha1, tree_type, &size, root);
+ tree = read_object_with_reference(tree_oid, tree_type, &size, &root);
if (!tree)
return -1;
if (name[0] == '\0') {
- hashcpy(sha1, root);
+ oidcpy(oid, &root);
free(tree);
return 0;
}
} else {
struct tree_desc t;
init_tree_desc(&t, tree, size);
- retval = find_tree_entry(&t, name, sha1, mode);
+ retval = find_tree_entry(&t, name, oid, mode);
}
free(tree);
return retval;
struct dir_state *parents = NULL;
size_t parents_alloc = 0;
size_t i, parents_nr = 0;
- unsigned char current_tree_sha1[20];
+ struct object_id current_tree_oid;
struct strbuf namebuf = STRBUF_INIT;
struct tree_desc t;
int follows_remaining = GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS;
init_tree_desc(&t, NULL, 0UL);
strbuf_addstr(&namebuf, name);
- hashcpy(current_tree_sha1, tree_sha1);
+ hashcpy(current_tree_oid.hash, tree_sha1);
while (1) {
int find_result;
if (!t.buffer) {
void *tree;
- unsigned char root[20];
+ struct object_id root;
unsigned long size;
- tree = read_object_with_reference(current_tree_sha1,
+ tree = read_object_with_reference(¤t_tree_oid,
tree_type, &size,
- root);
+ &root);
if (!tree)
goto done;
ALLOC_GROW(parents, parents_nr + 1, parents_alloc);
parents[parents_nr].tree = tree;
parents[parents_nr].size = size;
- hashcpy(parents[parents_nr].sha1, root);
+ hashcpy(parents[parents_nr].sha1, root.hash);
parents_nr++;
if (namebuf.buf[0] == '\0') {
- hashcpy(result, root);
+ hashcpy(result, root.hash);
retval = FOUND;
goto done;
}
/* Look up the first (or only) path component in the tree. */
find_result = find_tree_entry(&t, namebuf.buf,
- current_tree_sha1, mode);
+ ¤t_tree_oid, mode);
if (find_result) {
goto done;
}
if (S_ISDIR(*mode)) {
if (!remainder) {
- hashcpy(result, current_tree_sha1);
+ hashcpy(result, current_tree_oid.hash);
retval = FOUND;
goto done;
}
1 + first_slash - namebuf.buf);
} else if (S_ISREG(*mode)) {
if (!remainder) {
- hashcpy(result, current_tree_sha1);
+ hashcpy(result, current_tree_oid.hash);
retval = FOUND;
} else {
retval = NOT_DIR;
*/
retval = DANGLING_SYMLINK;
- contents = read_sha1_file(current_tree_sha1, &type,
- &link_len);
+ contents = read_object_file(¤t_tree_oid, &type,
+ &link_len);
if (!contents)
goto done;
int show_all_errors;
};
-int get_tree_entry(const unsigned char *, const char *, unsigned char *, unsigned *);
+int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned *);
extern char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n);
extern void setup_traverse_info(struct traverse_info *info, const char *base);
const char *tree_type = "tree";
static int read_one_entry_opt(struct index_state *istate,
- const unsigned char *sha1,
+ const struct object_id *oid,
const char *base, int baselen,
const char *pathname,
unsigned mode, int stage, int opt)
ce->ce_namelen = baselen + len;
memcpy(ce->name, base, baselen);
memcpy(ce->name + baselen, pathname, len+1);
- hashcpy(ce->oid.hash, sha1);
+ oidcpy(&ce->oid, oid);
return add_index_entry(istate, ce, opt);
}
-static int read_one_entry(const unsigned char *sha1, struct strbuf *base,
+static int read_one_entry(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode, int stage,
void *context)
{
struct index_state *istate = context;
- return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
+ return read_one_entry_opt(istate, oid, base->buf, base->len, pathname,
mode, stage,
ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
}
* This is used when the caller knows there is no existing entries at
* the stage that will conflict with the entry being added.
*/
-static int read_one_entry_quick(const unsigned char *sha1, struct strbuf *base,
+static int read_one_entry_quick(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode, int stage,
void *context)
{
struct index_state *istate = context;
- return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname,
+ return read_one_entry_opt(istate, oid, base->buf, base->len, pathname,
mode, stage,
ADD_CACHE_JUST_APPEND);
}
continue;
}
- switch (fn(entry.oid->hash, base,
+ switch (fn(entry.oid, base,
entry.path, entry.mode, stage, context)) {
case 0:
continue;
if (item->object.parsed)
return 0;
- buffer = read_sha1_file(item->object.oid.hash, &type, &size);
+ buffer = read_object_file(&item->object.oid, &type, &size);
if (!buffer)
return quiet_on_missing ? -1 :
error("Could not read %s",
struct tree *parse_tree_indirect(const struct object_id *oid);
#define READ_TREE_RECURSIVE 1
-typedef int (*read_tree_fn_t)(const unsigned char *, struct strbuf *, const char *, unsigned int, int, void *);
+typedef int (*read_tree_fn_t)(const struct object_id *, struct strbuf *, const char *, unsigned int, int, void *);
extern int read_tree_recursive(struct tree *tree,
const char *base, int baselen,
strbuf_trim(split[1]);
if (!get_oid(split[1]->buf, &oid)) {
strbuf_reset(split[1]);
- strbuf_add_unique_abbrev(split[1], oid.hash,
+ strbuf_add_unique_abbrev(split[1], &oid,
DEFAULT_ABBREV);
strbuf_addch(split[1], ' ');
strbuf_reset(line);
const char *color)
{
status_printf_ln(s, color, _("You are currently cherry-picking commit %s."),
- find_unique_abbrev(state->cherry_pick_head_sha1, DEFAULT_ABBREV));
+ find_unique_abbrev(&state->cherry_pick_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
const char *color)
{
status_printf_ln(s, color, _("You are currently reverting commit %s."),
- find_unique_abbrev(state->revert_head_sha1, DEFAULT_ABBREV));
+ find_unique_abbrev(&state->revert_head_oid, DEFAULT_ABBREV));
if (s->hints) {
if (has_unmerged(s))
status_printf_ln(s, color,
;
else if (!get_oid_hex(sb.buf, &oid)) {
strbuf_reset(&sb);
- strbuf_add_unique_abbrev(&sb, oid.hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&sb, &oid, DEFAULT_ABBREV);
} else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */
goto got_nothing;
else /* bisect */
if (!strcmp(cb->buf.buf, "HEAD")) {
/* HEAD is relative. Resolve it to the right reflog entry. */
strbuf_reset(&cb->buf);
- strbuf_add_unique_abbrev(&cb->buf, noid->hash, DEFAULT_ABBREV);
+ strbuf_add_unique_abbrev(&cb->buf, noid, DEFAULT_ABBREV);
}
return 1;
}
state->detached_from = xstrdup(from);
} else
state->detached_from =
- xstrdup(find_unique_abbrev(cb.noid.hash, DEFAULT_ABBREV));
- hashcpy(state->detached_sha1, cb.noid.hash);
+ xstrdup(find_unique_abbrev(&cb.noid, DEFAULT_ABBREV));
+ oidcpy(&state->detached_oid, &cb.noid);
state->detached_at = !get_oid("HEAD", &oid) &&
- !hashcmp(oid.hash, state->detached_sha1);
+ !oidcmp(&oid, &state->detached_oid);
free(ref);
strbuf_release(&cb.buf);
} else if (!stat(git_path_cherry_pick_head(), &st) &&
!get_oid("CHERRY_PICK_HEAD", &oid)) {
state->cherry_pick_in_progress = 1;
- hashcpy(state->cherry_pick_head_sha1, oid.hash);
+ oidcpy(&state->cherry_pick_head_oid, &oid);
}
wt_status_check_bisect(NULL, state);
if (!stat(git_path_revert_head(), &st) &&
!get_oid("REVERT_HEAD", &oid)) {
state->revert_in_progress = 1;
- hashcpy(state->revert_head_sha1, oid.hash);
+ oidcpy(&state->revert_head_oid, &oid);
}
if (get_detached_from)
char *branch;
char *onto;
char *detached_from;
- unsigned char detached_sha1[20];
- unsigned char revert_head_sha1[20];
- unsigned char cherry_pick_head_sha1[20];
+ struct object_id detached_oid;
+ struct object_id revert_head_oid;
+ struct object_id cherry_pick_head_oid;
};
size_t wt_status_locate_end(const char *s, size_t len);
return;
}
- ptr->ptr = read_sha1_file(oid->hash, &type, &size);
+ ptr->ptr = read_object_file(oid, &type, &size);
if (!ptr->ptr || type != OBJ_BLOB)
die("unable to read blob object %s", oid_to_hex(oid));
ptr->size = size;