Merge branch 'jc/apply'
authorJunio C Hamano <junkio@cox.net>
Mon, 28 Aug 2006 00:51:05 +0000 (17:51 -0700)
committerJunio C Hamano <junkio@cox.net>
Mon, 28 Aug 2006 00:51:05 +0000 (17:51 -0700)
* jc/apply:
git-apply --reject: finishing touches.
apply --reject: count hunks starting from 1, not 0
git-apply --verbose
git-apply --reject: send rejects to .rej files.
git-apply --reject
apply --reverse: tie it all together.
diff.c: make binary patch reversible.
builtin-apply --reverse: two bugfixes.

86 files changed:
Documentation/git-apply.txt
Documentation/git-blame.txt
Documentation/git-ls-remote.txt
Documentation/git-svn.txt
Documentation/git-update-index.txt
Documentation/git-zip-tree.txt [new file with mode: 0644]
Documentation/git.txt
Documentation/gitk.txt
Makefile
blame.c
builtin-apply.c
builtin-cat-file.c
builtin-checkout-index.c
builtin-commit-tree.c
builtin-diff-stages.c
builtin-diff.c
builtin-fmt-merge-msg.c
builtin-grep.c
builtin-log.c
builtin-mv.c
builtin-pack-objects.c
builtin-push.c
builtin-read-tree.c
builtin-show-branch.c
builtin-tar-tree.c
builtin-unpack-objects.c
builtin-update-index.c
builtin-update-ref.c
builtin-write-tree.c
builtin-zip-tree.c [new file with mode: 0644]
builtin.h
cache-tree.c
cache.h
combine-diff.c
commit.c
connect.c
contrib/gitview/gitview.txt
convert-objects.c
csum-file.c
daemon.c
date.c
describe.c
diff-delta.c
diff-lib.c
diff.c
diffcore-break.c
diffcore-rename.c
dir.c
dump-cache-tree.c
entry.c
environment.c
fetch-pack.c
fetch.c
fsck-objects.c
git-cherry.sh
git-compat-util.h
git-reset.sh
git-send-email.perl
git-svn.perl
git.c
gitweb/gitweb.perl
http-fetch.c
http-push.c
index-pack.c
merge-tree.c
mktree.c
object.c
pack-check.c
pack-redundant.c
patch-id.c
read-cache.c
receive-pack.c
refs.c
revision.c
send-pack.c
sha1_file.c
sha1_name.c
ssh-fetch.c
t/t7001-mv.sh
tree-diff.c
tree-walk.c
tree.c
unpack-trees.c
upload-pack.c
write_or_die.c [new file with mode: 0644]
xdiff-interface.c
index 2e2acd72c7ebbe3d099456e27595b20d9d001d78..c76cfffdc6cd9982aa02e34b2b09fc22897e7402 100644 (file)
@@ -10,10 +10,10 @@ SYNOPSIS
 --------
 [verse]
 'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply]
-         [--no-add] [--index-info] [--allow-binary-replacement]
-         [--reverse] [--reject] [-z] [-pNUM]
-         [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>]
-         [<patch>...]
+         [--no-add] [--index-info] [--allow-binary-replacement | --binary]
+         [-R | --reverse] [--reject] [-z] [-pNUM] [-CNUM] [--inaccurate-eof]
+         [--whitespace=<nowarn|warn|error|error-all|strip>] [--exclude=PATH]
+         [--cached] [--verbose] [<patch>...]
 
 DESCRIPTION
 -----------
@@ -56,6 +56,11 @@ OPTIONS
        up-to-date, it is flagged as an error.  This flag also
        causes the index file to be updated.
 
+--cached::
+       Apply a patch without touching the working tree. Instead, take the
+       cached data, apply the patch, and store the result in the index,
+       without using the working tree. This implies '--index'.
+
 --index-info::
        Newer git-diff output has embedded 'index information'
        for each blob to help identify the original version that
@@ -63,14 +68,14 @@ OPTIONS
        the original version of the blob is available locally,
        outputs information about them to the standard output.
 
---reverse::
+-R, --reverse::
        Apply the patch in reverse.
 
 --reject::
-       For atomicity, `git apply` fails the whole patch and
+       For atomicity, gitlink:git-apply[1] by default fails the whole patch and
        does not touch the working tree when some of the hunks
-       do not apply by default.  This option makes it apply
-       parts of the patch that are applicable, and leave the
+       do not apply.  This option makes it apply
+       the parts of the patch that are applicable, and leave the
        rejected hunks in corresponding *.rej files.
 
 -z::
@@ -91,8 +96,8 @@ OPTIONS
        ever ignored.
 
 --apply::
-       If you use any of the options marked ``Turns off
-       "apply"'' above, git-apply reads and outputs the
+       If you use any of the options marked "Turns off
+       'apply'" above, gitlink:git-apply[1] reads and outputs the
        information you asked without actually applying the
        patch.  Give this flag after those flags to also apply
        the patch.
@@ -104,7 +109,7 @@ OPTIONS
        the result with this option, which would apply the
        deletion part but not addition part.
 
---allow-binary-replacement::
+--allow-binary-replacement, --binary::
        When applying a patch, which is a git-enhanced patch
        that was prepared to record the pre- and post-image object
        name in full, and the path being patched exactly matches
@@ -115,13 +120,18 @@ OPTIONS
        result.  This allows binary files to be patched in a
        very limited way.
 
+--exclude=<path-pattern>::
+       Don't apply changes to files matching the given path pattern. This can
+       be useful when importing patchsets, where you want to exclude certain
+       files or directories.
+
 --whitespace=<option>::
        When applying a patch, detect a new or modified line
        that ends with trailing whitespaces (this includes a
        line that solely consists of whitespaces).  By default,
        the command outputs warning messages and applies the
        patch.
-       When `git-apply` is used for statistics and not applying a
+       When gitlink:git-apply[1] is used for statistics and not applying a
        patch, it defaults to `nowarn`.
        You can use different `<option>` to control this
        behavior:
@@ -135,6 +145,17 @@ OPTIONS
 * `strip` outputs warnings for a few such errors, strips out the
   trailing whitespaces and applies the patch.
 
+--inacurate-eof::
+       Under certain circumstances, some versions of diff do not correctly
+       detect a missing new-line at the end of the file. As a result, patches
+       created by such diff programs do not record incomplete lines
+       correctly. This option adds support for applying such patches by
+       working around this bug.
+
+--verbose::
+       Report progress to stderr. By default, only a message about the
+       current patch being applied will be printed. This option will cause
+       additional information to be reported.
 
 Configuration
 -------------
index bfed945914c5de74d6f46e51ee8fbe459e4d8420..e1f89444a95618a1e520940a79389c854cf9d576 100644 (file)
@@ -3,21 +3,38 @@ git-blame(1)
 
 NAME
 ----
-git-blame - Blame file lines on commits
+git-blame - Show what revision and author last modified each line of a file
 
 SYNOPSIS
 --------
-git-blame file [options] file [revision]
+'git-blame' [-c] [-l] [-t] [-S <revs-file>] [--] <file> [<rev>]
 
 DESCRIPTION
 -----------
-Annotates each line in the given file with information from the commit
-which introduced the line. Start annotation from the given revision.
+
+Annotates each line in the given file with information from the revision which
+last modified the line. Optionally, start annotating from the given revision.
+
+This report doesn't tell you anything about lines which have been deleted or
+replaced; you need to use a tool such as gitlink:git-diff[1] or the "pickaxe"
+interface briefly mentioned in the following paragraph.
+
+Apart from supporting file annotation, git also supports searching the
+development history for when a code snippet occured in a change. This makes it
+possible to track when a code snippet was added to a file, moved or copied
+between files, and eventually deleted or replaced. It works by searching for
+a text string in the diff. A small example:
+
+-----------------------------------------------------------------------------
+$ git log --pretty=oneline -S'blame_usage'
+5040f17eba15504bad66b14a645bddd9b015ebb7 blame -S <ancestry-file>
+ea4c7f9bf69e781dd0cd88d2bccb2bf5cc15c9a7 git-blame: Make the output
+-----------------------------------------------------------------------------
 
 OPTIONS
 -------
 -c, --compatibility::
-       Use the same output mode as git-annotate (Default: off).
+       Use the same output mode as gitlink:git-annotate[1] (Default: off).
 
 -l, --long::
        Show long rev (Default: off).
@@ -26,7 +43,7 @@ OPTIONS
        Show raw timestamp (Default: off).
 
 -S, --rev-file <revs-file>::
-       Use revs from revs-file instead of calling git-rev-list.
+       Use revs from revs-file instead of calling gitlink:git-rev-list[1].
 
 -h, --help::
        Show help message.
index ae4c1a250e835bd39ee291088ba74c3c57604ac9..c8a4c5a4d9d2bead8686f1b582e985531a7f3591 100644 (file)
@@ -3,16 +3,19 @@ git-ls-remote(1)
 
 NAME
 ----
-git-ls-remote - Look at references other repository has
+git-ls-remote - List references in a remote repository
 
 
 SYNOPSIS
 --------
-'git-ls-remote' [--heads] [--tags] <repository> <refs>...
+[verse]
+'git-ls-remote' [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]
+             <repository> <refs>...
 
 DESCRIPTION
 -----------
-Displays the references other repository has.
+Displays references available in a remote repository along with the associated
+commit IDs.
 
 
 OPTIONS
@@ -23,9 +26,16 @@ OPTIONS
        both, references stored in refs/heads and refs/tags are
        displayed.
 
+-u <exec>, --upload-pack=<exec>::
+       Specify the full path of gitlink:git-upload-pack[1] on the remote
+       host. This allows listing references from repositories accessed via
+       SSH and where the SSH deamon does not use the PATH configured by the
+       user. Also see the '--exec' option for gitlink:git-peek-remote[1].
+
 <repository>::
        Location of the repository.  The shorthand defined in
-       $GIT_DIR/branches/ can be used.
+       $GIT_DIR/branches/ can be used. Use "." (dot) to list references in
+       the local repository.
 
 <refs>...::
        When unspecified, all references, after filtering done
index 7d868098448c7cc6712988c7bb1df541aedf6824..b7b63f7136a01d6f3383346c292e5c8aceb8ced4 100644 (file)
@@ -12,10 +12,8 @@ SYNOPSIS
 DESCRIPTION
 -----------
 git-svn is a simple conduit for changesets between a single Subversion
-branch and git.
-
-git-svn is not to be confused with git-svnimport.  The were designed
-with very different goals in mind.
+branch and git. It is not to be confused with gitlink:git-svnimport[1].
+They were designed with very different goals in mind.
 
 git-svn is designed for an individual developer who wants a
 bidirectional flow of changesets between a single branch in Subversion
@@ -34,26 +32,38 @@ git-svnimport is designed for.
 
 COMMANDS
 --------
-init::
+--
+
+'init'::
        Creates an empty git repository with additional metadata
        directories for git-svn.  The Subversion URL must be specified
        as a command-line argument.
 
-fetch::
-       Fetch unfetched revisions from the Subversion URL we are
-       tracking.  refs/remotes/git-svn will be updated to the
-       latest revision.
+'fetch'::
+
+Fetch unfetched revisions from the Subversion URL we are
+tracking.  refs/remotes/git-svn will be updated to the
+latest revision.
+
+Note: You should never attempt to modify the remotes/git-svn
+branch outside of git-svn.  Instead, create a branch from
+remotes/git-svn and work on that branch.  Use the 'commit'
+command (see below) to write git commits back to
+remotes/git-svn.
 
-       Note: You should never attempt to modify the remotes/git-svn
-       branch outside of git-svn.  Instead, create a branch from
-       remotes/git-svn and work on that branch.  Use the 'commit'
-       command (see below) to write git commits back to
-       remotes/git-svn.
+See '<<fetch-args,Additional Fetch Arguments>>' if you are interested in
+manually joining branches on commit.
 
-       See 'Additional Fetch Arguments' if you are interested in
-       manually joining branches on commit.
+'dcommit'::
+       Commit all diffs from the current HEAD directly to the SVN
+       repository, and then rebase or reset (depending on whether or
+       not there is a diff between SVN and HEAD).  It is recommended
+       that you run git-svn fetch and rebase (not pull) your commits
+       against the latest changes in the SVN repository.
+       This is advantageous over 'commit' (below) because it produces
+       cleaner, more linear history.
 
-commit::
+'commit'::
        Commit specified commit or tree objects to SVN.  This relies on
        your imported fetch data being up-to-date.  This makes
        absolutely no attempts to do patching when committing to SVN, it
@@ -61,9 +71,9 @@ commit::
        commit.  All merging is assumed to have taken place
        independently of git-svn functions.
 
-rebuild::
+'rebuild'::
        Not a part of daily usage, but this is a useful command if
-       you've just cloned a repository (using git-clone) that was
+       you've just cloned a repository (using gitlink:git-clone[1]) that was
        tracked with git-svn.  Unfortunately, git-clone does not clone
        git-svn metadata and the svn working tree that git-svn uses for
        its operations.  This rebuilds the metadata so git-svn can
@@ -71,130 +81,170 @@ rebuild::
        specified at the command-line if the directory/repository you're
        tracking has moved or changed protocols.
 
-show-ignore::
+'show-ignore'::
        Recursively finds and lists the svn:ignore property on
        directories.  The output is suitable for appending to
        the $GIT_DIR/info/exclude file.
 
+--
+
 OPTIONS
 -------
+--
+
 -r <ARG>::
 --revision <ARG>::
-       Only used with the 'fetch' command.
 
-       Takes any valid -r<argument> svn would accept and passes it
-       directly to svn. -r<ARG1>:<ARG2> ranges and "{" DATE "}" syntax
-       is also supported.  This is passed directly to svn, see svn
-       documentation for more details.
+Only used with the 'fetch' command.
+
+Takes any valid -r<argument> svn would accept and passes it
+directly to svn. -r<ARG1>:<ARG2> ranges and "{" DATE "}" syntax
+is also supported.  This is passed directly to svn, see svn
+documentation for more details.
 
-       This can allow you to make partial mirrors when running fetch.
+This can allow you to make partial mirrors when running fetch.
 
 -::
 --stdin::
-       Only used with the 'commit' command.
 
-       Read a list of commits from stdin and commit them in reverse
-       order.  Only the leading sha1 is read from each line, so
-       git-rev-list --pretty=oneline output can be used.
+Only used with the 'commit' command.
+
+Read a list of commits from stdin and commit them in reverse
+order.  Only the leading sha1 is read from each line, so
+git-rev-list --pretty=oneline output can be used.
 
 --rmdir::
-       Only used with the 'commit' command.
 
-       Remove directories from the SVN tree if there are no files left
-       behind.  SVN can version empty directories, and they are not
-       removed by default if there are no files left in them.  git
-       cannot version empty directories.  Enabling this flag will make
-       the commit to SVN act like git.
+Only used with the 'commit' command.
+
+Remove directories from the SVN tree if there are no files left
+behind.  SVN can version empty directories, and they are not
+removed by default if there are no files left in them.  git
+cannot version empty directories.  Enabling this flag will make
+the commit to SVN act like git.
 
-       repo-config key: svn.rmdir
+repo-config key: svn.rmdir
 
 -e::
 --edit::
-       Only used with the 'commit' command.
 
-       Edit the commit message before committing to SVN.  This is off by
-       default for objects that are commits, and forced on when committing
-       tree objects.
+Only used with the 'commit' command.
 
-       repo-config key: svn.edit
+Edit the commit message before committing to SVN.  This is off by
+default for objects that are commits, and forced on when committing
+tree objects.
+
+repo-config key: svn.edit
 
 -l<num>::
 --find-copies-harder::
-       Both of these are only used with the 'commit' command.
 
-       They are both passed directly to git-diff-tree see
-       git-diff-tree(1) for more information.
+Both of these are only used with the 'commit' command.
+
+They are both passed directly to git-diff-tree see
+gitlink:git-diff-tree[1] for more information.
 
-       repo-config key: svn.l
-       repo-config key: svn.findcopiesharder
+[verse]
+repo-config key: svn.l
+repo-config key: svn.findcopiesharder
 
 -A<filename>::
 --authors-file=<filename>::
 
-       Syntax is compatible with the files used by git-svnimport and
-       git-cvsimport:
+Syntax is compatible with the files used by git-svnimport and
+git-cvsimport:
 
 ------------------------------------------------------------------------
-loginname = Joe User <user@example.com>
+       loginname = Joe User <user@example.com>
 ------------------------------------------------------------------------
 
-       If this option is specified and git-svn encounters an SVN
-       committer name that does not exist in the authors-file, git-svn
-       will abort operation. The user will then have to add the
-       appropriate entry.  Re-running the previous git-svn command
-       after the authors-file is modified should continue operation.
+If this option is specified and git-svn encounters an SVN
+committer name that does not exist in the authors-file, git-svn
+will abort operation. The user will then have to add the
+appropriate entry.  Re-running the previous git-svn command
+after the authors-file is modified should continue operation.
+
+repo-config key: svn.authors-file
+
+-m::
+--merge::
+-s<strategy>::
+--strategy=<strategy>::
+
+These are only used with the 'dcommit' command.
 
-       repo-config key: svn.authors-file
+Passed directly to git-rebase when using 'dcommit' if a
+'git-reset' cannot be used (see dcommit).
+
+-n::
+--dry-run::
+
+This is only used with the 'dcommit' command.
+
+Print out the series of git arguments that would show
+which diffs would be committed to SVN.
+
+--
 
 ADVANCED OPTIONS
 ----------------
+--
+
 -b<refname>::
 --branch <refname>::
-       Used with 'fetch' or 'commit'.
+Used with 'fetch' or 'commit'.
 
-       This can be used to join arbitrary git branches to remotes/git-svn
-       on new commits where the tree object is equivalent.
+This can be used to join arbitrary git branches to remotes/git-svn
+on new commits where the tree object is equivalent.
 
-       When used with different GIT_SVN_ID values, tags and branches in
-       SVN can be tracked this way, as can some merges where the heads
-       end up having completely equivalent content.  This can even be
-       used to track branches across multiple SVN _repositories_.
+When used with different GIT_SVN_ID values, tags and branches in
+SVN can be tracked this way, as can some merges where the heads
+end up having completely equivalent content.  This can even be
+used to track branches across multiple SVN _repositories_.
 
-       This option may be specified multiple times, once for each
-       branch.
+This option may be specified multiple times, once for each
+branch.
 
-       repo-config key: svn.branch
+repo-config key: svn.branch
 
 -i<GIT_SVN_ID>::
 --id <GIT_SVN_ID>::
-       This sets GIT_SVN_ID (instead of using the environment).  See
-       the section on "Tracking Multiple Repositories or Branches" for
-       more information on using GIT_SVN_ID.
+
+This sets GIT_SVN_ID (instead of using the environment).  See the
+section on
+'<<tracking-multiple-repos,Tracking Multiple Repositories or Branches>>'
+for more information on using GIT_SVN_ID.
+
+--
 
 COMPATIBILITY OPTIONS
 ---------------------
+--
+
 --upgrade::
-       Only used with the 'rebuild' command.
+Only used with the 'rebuild' command.
 
-       Run this if you used an old version of git-svn that used
-       "git-svn-HEAD" instead of "remotes/git-svn" as the branch
-       for tracking the remote.
+Run this if you used an old version of git-svn that used
+"git-svn-HEAD" instead of "remotes/git-svn" as the branch
+for tracking the remote.
 
 --no-ignore-externals::
-       Only used with the 'fetch' and 'rebuild' command.
+Only used with the 'fetch' and 'rebuild' command.
+
+By default, git-svn passes --ignore-externals to svn to avoid
+fetching svn:external trees into git.  Pass this flag to enable
+externals tracking directly via git.
 
-       By default, git-svn passes --ignore-externals to svn to avoid
-       fetching svn:external trees into git.  Pass this flag to enable
-       externals tracking directly via git.
+Versions of svn that do not support --ignore-externals are
+automatically detected and this flag will be automatically
+enabled for them.
 
-       Versions of svn that do not support --ignore-externals are
-       automatically detected and this flag will be automatically
-       enabled for them.
+Otherwise, do not enable this flag unless you know what you're
+doing.
 
-       Otherwise, do not enable this flag unless you know what you're
-       doing.
+repo-config key: svn.noignoreexternals
 
-       repo-config key: svn.noignoreexternals
+--
 
 Basic Examples
 ~~~~~~~~~~~~~~
@@ -212,12 +262,26 @@ Tracking and contributing to an Subversion managed-project:
        git-svn commit <tree-ish> [<tree-ish_2> ...]
 # Commit all the git commits from my-branch that don't exist in SVN:
        git-svn commit remotes/git-svn..my-branch
-# Something is committed to SVN, pull the latest into your branch:
-       git-svn fetch && git pull . remotes/git-svn
+# Something is committed to SVN, rebase the latest into your branch:
+       git-svn fetch && git rebase remotes/git-svn
 # Append svn:ignore settings to the default git exclude file:
        git-svn show-ignore >> .git/info/exclude
 ------------------------------------------------------------------------
 
+REBASE VS. PULL
+---------------
+
+Originally, git-svn recommended that the remotes/git-svn branch be
+pulled from.  This is because the author favored 'git-svn commit B'
+to commit a single head rather than the 'git-svn commit A..B' notation
+to commit multiple commits.
+
+If you use 'git-svn commit A..B' to commit several diffs and you do not
+have the latest remotes/git-svn merged into my-branch, you should use
+'git rebase' to update your work branch instead of 'git pull'.  'pull'
+can cause non-linear history to be flattened when committing into SVN,
+which can lead to merge commits reversing previous commits in SVN.
+
 DESIGN PHILOSOPHY
 -----------------
 Merge tracking in Subversion is lacking and doing branched development
@@ -226,6 +290,7 @@ any automated merge/branch tracking on the Subversion side and leaves it
 entirely up to the user on the git side.  It's simply not worth it to do
 a useful translation when the original signal is weak.
 
+[[tracking-multiple-repos]]
 TRACKING MULTIPLE REPOSITORIES OR BRANCHES
 ------------------------------------------
 This is for advanced users, most users should ignore this section.
@@ -241,6 +306,7 @@ invocation.  The interface branch will be remotes/$GIT_SVN_ID, instead of
 remotes/git-svn.  Any remotes/$GIT_SVN_ID branch should never be modified
 by the user outside of git-svn commands.
 
+[[fetch-args]]
 ADDITIONAL FETCH ARGUMENTS
 --------------------------
 This is for advanced users, most users should ignore this section.
@@ -251,11 +317,15 @@ optionally be specified in the form of sha1 hex sums at the
 command-line.  Unfetched SVN revisions may also be tied to particular
 git commits with the following syntax:
 
+------------------------------------------------
        svn_revision_number=git_commit_sha1
+------------------------------------------------
 
-This allows you to tie unfetched SVN revision 375 to your current HEAD::
+This allows you to tie unfetched SVN revision 375 to your current HEAD:
 
-       `git-svn fetch 375=$(git-rev-parse HEAD)`
+------------------------------------------------
+       git-svn fetch 375=$(git-rev-parse HEAD)
+------------------------------------------------
 
 Advanced Example: Tracking a Reorganized Repository
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -310,6 +380,10 @@ the possible corner cases (git doesn't do it, either).  Renamed and
 copied files are fully supported if they're similar enough for git to
 detect them.
 
+SEE ALSO
+--------
+gitlink:git-rebase[1]
+
 Author
 ------
 Written by Eric Wong <normalperson@yhbt.net>.
index 3ae6e74573d1b5f651f8dabc6c9569b05e049b10..41bb7e12e3d89e4876a60ea7733cffcaf09cd6ed 100644 (file)
@@ -15,7 +15,7 @@ SYNOPSIS
             [--cacheinfo <mode> <object> <file>]\*
             [--chmod=(+|-)x]
             [--assume-unchanged | --no-assume-unchanged]
-            [--really-refresh] [--unresolve] [--again]
+            [--really-refresh] [--unresolve] [--again | -g]
             [--info-only] [--index-info]
             [-z] [--stdin]
             [--verbose]
@@ -80,7 +80,7 @@ OPTIONS
        filesystem that has very slow lstat(2) system call
        (e.g. cifs).
 
---again::
+--again, -g::
        Runs `git-update-index` itself on the paths whose index
        entries are different from those from the `HEAD` commit.
 
diff --git a/Documentation/git-zip-tree.txt b/Documentation/git-zip-tree.txt
new file mode 100644 (file)
index 0000000..2e9d981
--- /dev/null
@@ -0,0 +1,67 @@
+git-zip-tree(1)
+===============
+
+NAME
+----
+git-zip-tree - Creates a ZIP archive of the files in the named tree
+
+
+SYNOPSIS
+--------
+'git-zip-tree' [-0|...|-9] <tree-ish> [ <base> ]
+
+DESCRIPTION
+-----------
+Creates a ZIP archive containing the tree structure for the named tree.
+When <base> is specified it is added as a leading path to the files in the
+generated ZIP archive.
+
+git-zip-tree behaves differently when given a tree ID versus when given
+a commit ID or tag ID.  In the first case the current time is used as
+modification time of each file in the archive.  In the latter case the
+commit time as recorded in the referenced commit object is used instead.
+Additionally the commit ID is stored as an archive comment.
+
+Currently git-zip-tree can handle only files and directories, symbolic
+links are not supported.
+
+OPTIONS
+-------
+
+-0::
+       Store the files instead of deflating them.
+
+-9::
+       Highest and slowest compression level.  You can specify any
+       number from 1 to 9 to adjust compression speed and ratio.
+
+<tree-ish>::
+       The tree or commit to produce ZIP archive for.  If it is
+       the object name of a commit object.
+
+<base>::
+       Leading path to the files in the resulting ZIP archive.
+
+EXAMPLES
+--------
+git zip-tree v1.4.0 git-1.4.0 >git-1.4.0.zip::
+
+       Create a ZIP file for v1.4.0 release.
+
+git zip-tree HEAD:Documentation/ git-docs >docs.zip::
+
+       Put everything in the current head's Documentation/ directory
+       into 'docs.zip', with the prefix 'git-docs/'.
+
+Author
+------
+Written by Rene Scharfe.
+
+Documentation
+--------------
+Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the gitlink:git[7] suite
+
index 3de5fa9c82de4d49a041480ce6681f69a97f167c..a9c87e38dae69b0799328917727867342eb5d22c 100644 (file)
@@ -8,8 +8,9 @@ git - the stupid content tracker
 
 SYNOPSIS
 --------
+[verse]
 'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate]
-       [--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]
+    [--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]
 
 DESCRIPTION
 -----------
index cb482bf98ef9e2509ab2d2e1665933687538a574..23be0050b0023cbfecc5fa271b97a7d9855a73b0 100644 (file)
@@ -3,26 +3,52 @@ gitk(1)
 
 NAME
 ----
-gitk - Some git command not yet documented.
-
+gitk - git repository browser
 
 SYNOPSIS
 --------
-'gitk' [ --option ] <args>...
+'gitk' [<option>...] [<revs>] [--] [<path>...]
 
 DESCRIPTION
 -----------
-Does something not yet documented.
+Displays changes in a repository or a selected set of commits. This includes
+visualizing the commit graph, showing information related to each commit, and
+the files in the trees of each revision.
 
+Historically, gitk was the first repository browser. It's written in tcl/tk
+and started off in a separate repository but was later merged into the main
+git repository.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
+To control which revisions to shown, the command takes options applicable to
+the gitlink:git-rev-list[1] command. This manual page describes only the most
+frequently used options.
+
+-n <number>, --max-count=<number>::
+
+       Limits the number of commits to show.
+
+--since=<date>::
+
+       Show commits more recent than a specific date.
+
+--until=<date>::
+
+       Show commits older than a specific date.
 
-<args>...::
-       Some argument not yet documented.
+<revs>::
 
+       Limit the revisions to show. This can be either a single revision
+       meaning show from the given revision and back, or it can be a range in
+       the form "'<from>'..'<to>'" to show all revisions between '<from>' and
+       back to '<to>'. Note, more advanced revision selection can be applied.
+
+<path>::
+
+       Limit commits to the ones touching files in the given paths. Note, to
+       avoid ambiguity wrt. revision names use "--" to separate the paths
+       from any preceeding options.
 
 Examples
 --------
@@ -37,13 +63,27 @@ gitk --since="2 weeks ago" \-- gitk::
        The "--" is necessary to avoid confusion with the *branch* named
        'gitk'
 
+See Also
+--------
+'qgit(1)'::
+       A repository browser written in C++ using Qt.
+
+'gitview(1)'::
+       A repository browser written in Python using Gtk. It's based on
+       'bzrk(1)' and distributed in the contrib area of the git repository.
+
+'tig(1)'::
+       A minimal repository browser and git tool output highlighter written
+       in C using Ncurses.
+
 Author
 ------
-Written by Paul Mackerras <paulus@samba.org>
+Written by Paul Mackerras <paulus@samba.org>.
 
 Documentation
 --------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
+Documentation by Junio C Hamano, Jonas Fonseca, and the git-list
+<git@vger.kernel.org>.
 
 GIT
 ---
index 23cd8a017ba05986c309c605ae06fba6a98e5c07..d9741f917f0dab4d9a7e98764fdb04d8f3443cb4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -248,6 +248,7 @@ LIB_OBJS = \
        server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
        tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
        fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
+       write_or_die.o \
        alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS)
 
 BUILTIN_OBJS = \
@@ -291,7 +292,8 @@ BUILTIN_OBJS = \
        builtin-update-ref.o \
        builtin-upload-tar.o \
        builtin-verify-pack.o \
-       builtin-write-tree.o
+       builtin-write-tree.o \
+       builtin-zip-tree.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
 LIBS = $(GITLIBS) -lz
diff --git a/blame.c b/blame.c
index c253b9ca45cf7d860052ddae95bc1ed34974ffb8..8968046b0045633e6046c3126978819e9910a5f2 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -165,7 +165,7 @@ static int get_blob_sha1(struct tree *t, const char *pathname,
        blame_file = pathname;
        pathspec[0] = pathname;
        pathspec[1] = NULL;
-       memset(blob_sha1, 0, sizeof(blob_sha1));
+       hashclr(blob_sha1);
        read_tree_recursive(t, "", 0, 0, pathspec, get_blob_sha1_internal);
 
        for (i = 0; i < 20; i++) {
@@ -176,7 +176,7 @@ static int get_blob_sha1(struct tree *t, const char *pathname,
        if (i == 20)
                return -1;
 
-       memcpy(sha1, blob_sha1, 20);
+       hashcpy(sha1, blob_sha1);
        return 0;
 }
 
@@ -191,7 +191,7 @@ static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
            strcmp(blame_file + baselen, pathname))
                return -1;
 
-       memcpy(blob_sha1, sha1, 20);
+       hashcpy(blob_sha1, sha1);
        return -1;
 }
 
index 0b00a98aa1b283796e0c67fb42e0c9a35d74ff5c..b47ccacc2e0618476ca4816e111a97b2c46f0f4f 100644 (file)
@@ -628,9 +628,7 @@ static char *git_header_name(char *line, int llen)
         * form.
         */
        for (len = 0 ; ; len++) {
-               char c = name[len];
-
-               switch (c) {
+               switch (name[len]) {
                default:
                        continue;
                case '\n':
@@ -1944,16 +1942,16 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
 static int check_patch_list(struct patch *patch)
 {
        struct patch *prev_patch = NULL;
-       int error = 0;
+       int err = 0;
 
        for (prev_patch = NULL; patch ; patch = patch->next) {
                if (apply_verbosely)
                        say_patch_name(stderr,
                                       "Checking patch ", patch, "...\n");
-               error |= check_patch(patch, prev_patch);
+               err |= check_patch(patch, prev_patch);
                prev_patch = patch;
        }
-       return error;
+       return err;
 }
 
 static void show_index_list(struct patch *list)
index df009ade7aae3ad82974a915efa16525e76ccaed..6c16bfa1ae4ae6207a74a8caa95564c649c4b0dd 100644 (file)
@@ -9,23 +9,6 @@
 #include "tree.h"
 #include "builtin.h"
 
-static void flush_buffer(const char *buf, unsigned long size)
-{
-       while (size > 0) {
-               long ret = xwrite(1, buf, size);
-               if (ret < 0) {
-                       /* Ignore epipe */
-                       if (errno == EPIPE)
-                               break;
-                       die("git-cat-file: %s", strerror(errno));
-               } else if (!ret) {
-                       die("git-cat-file: disk full?");
-               }
-               size -= ret;
-               buf += ret;
-       }
-}
-
 static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long size)
 {
        /* the parser in tag.c is useless here. */
@@ -42,7 +25,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
                        /* Found the tagger line.  Copy out the contents
                         * of the buffer so far.
                         */
-                       flush_buffer(buf, cp - buf);
+                       write_or_die(1, buf, cp - buf);
 
                        /*
                         * Do something intelligent, like pretty-printing
@@ -61,18 +44,18 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
                                                sp++;
                                        if (sp == cp) {
                                                /* give up */
-                                               flush_buffer(tagger,
+                                               write_or_die(1, tagger,
                                                             cp - tagger);
                                                break;
                                        }
                                        while (sp < cp &&
                                               !('0' <= *sp && *sp <= '9'))
                                                sp++;
-                                       flush_buffer(tagger, sp - tagger);
+                                       write_or_die(1, tagger, sp - tagger);
                                        date = strtoul(sp, &ep, 10);
                                        tz = strtol(ep, NULL, 10);
-                                       sp = show_date(date, tz);
-                                       flush_buffer(sp, strlen(sp));
+                                       sp = show_date(date, tz, 0);
+                                       write_or_die(1, sp, strlen(sp));
                                        xwrite(1, "\n", 1);
                                        break;
                                }
@@ -90,7 +73,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
         * remainder as is.
         */
        if (cp < endp)
-               flush_buffer(cp, endp - cp);
+               write_or_die(1, cp, endp - cp);
 }
 
 int cmd_cat_file(int argc, const char **argv, const char *prefix)
@@ -162,6 +145,6 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
        if (!buf)
                die("git-cat-file %s: bad file", argv[2]);
 
-       flush_buffer(buf, size);
+       write_or_die(1, buf, size);
        return 0;
 }
index 6b55f931cbd8b79a01057b55eb41a043a4db5e3b..b097c888a0da044d6dc78c9747eb18e45b46709d 100644 (file)
@@ -45,7 +45,7 @@
 static int line_termination = '\n';
 static int checkout_stage; /* default to checkout stage0 */
 static int to_tempfile;
-static char topath[4][MAXPATHLEN+1];
+static char topath[4][PATH_MAX + 1];
 
 static struct checkout state;
 
index 9c987966711d4bff1f709df0c14071170950e21d..e2e690a1ae89b47f595288e452da10113f7b2e8f 100644 (file)
@@ -69,7 +69,7 @@ static int new_parent(int idx)
        int i;
        unsigned char *sha1 = parent_sha1[idx];
        for (i = 0; i < idx; i++) {
-               if (!memcmp(parent_sha1[i], sha1, 20)) {
+               if (!hashcmp(parent_sha1[i], sha1)) {
                        error("duplicate parent %s ignored", sha1_to_hex(sha1));
                        return 0;
                }
index 5960e089975f1f27c55c5bd8ea1c968ffe695d1f..70bb89808d2296246edbafb8378aa651c3382261 100644 (file)
@@ -46,7 +46,7 @@ static void diff_stages(int stage1, int stage2, const char **pathspec)
                else if (!two)
                        diff_addremove(&diff_options, '-', ntohl(one->ce_mode),
                                       one->sha1, name, NULL);
-               else if (memcmp(one->sha1, two->sha1, 20) ||
+               else if (hashcmp(one->sha1, two->sha1) ||
                         (one->ce_mode != two->ce_mode) ||
                         diff_options.find_copies_harder)
                        diff_change(&diff_options,
index 40e5c96f30e3d638c09b276805158bdba3ddde58..a6590205e8f746304f3d06d3e328a05bf2bf954e 100644 (file)
@@ -69,7 +69,7 @@ static void stuff_change(struct diff_options *opt,
        struct diff_filespec *one, *two;
 
        if (!is_null_sha1(old_sha1) && !is_null_sha1(new_sha1) &&
-           !memcmp(old_sha1, new_sha1, 20))
+           !hashcmp(old_sha1, new_sha1))
                return;
 
        if (opt->reverse_diff) {
@@ -192,7 +192,7 @@ static int builtin_diff_combined(struct rev_info *revs,
        parent = xmalloc(ents * sizeof(*parent));
        /* Again, the revs are all reverse */
        for (i = 0; i < ents; i++)
-               memcpy(parent + i, ent[ents - 1 - i].item->sha1, 20);
+               hashcpy((unsigned char*)parent + i, ent[ents - 1 - i].item->sha1);
        diff_tree_combined(parent[0], parent + 1, ents - 1,
                           revs->dense_combined_merges, revs);
        return 0;
@@ -290,7 +290,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                if (obj->type == OBJ_BLOB) {
                        if (2 <= blobs)
                                die("more than two blobs given: '%s'", name);
-                       memcpy(blob[blobs].sha1, obj->sha1, 20);
+                       hashcpy(blob[blobs].sha1, obj->sha1);
                        blob[blobs].name = name;
                        blobs++;
                        continue;
index 28b5dfd054ea8277379d6913b1f1c4cde225e70d..a5ed8dbbac2a1320e7cf61e16eeccdf5c5cee915 100644 (file)
@@ -27,8 +27,8 @@ static void append_to_list(struct list *list, char *value, void *payload)
 {
        if (list->nr == list->alloc) {
                list->alloc += 32;
-               list->list = realloc(list->list, sizeof(char *) * list->alloc);
-               list->payload = realloc(list->payload,
+               list->list = xrealloc(list->list, sizeof(char *) * list->alloc);
+               list->payload = xrealloc(list->payload,
                                sizeof(char *) * list->alloc);
        }
        list->payload[list->nr] = payload;
index 0bd517b2649af37d9980f85e784f9a00c3263922..8213ce240232a1dc8a0a498972323a33e8fcb7a0 100644 (file)
@@ -293,9 +293,6 @@ static void compile_patterns(struct grep_opt *opt)
         */
        p = opt->pattern_list;
        opt->pattern_expression = compile_pattern_expr(&p);
-#if DEBUG
-       dump_pattern_exp(opt->pattern_expression, 0);
-#endif
        if (p)
                die("incomplete pattern expression: %s", p->pattern);
 }
index 691cf3aef785950132c6be65f8aab39d4b12207e..fbc58bbcab1a992efb6ee359171d7ed6f0c52ab9 100644 (file)
@@ -101,7 +101,7 @@ static int git_format_config(const char *var, const char *value)
        if (!strcmp(var, "format.headers")) {
                int len = strlen(value);
                extra_headers_size += len + 1;
-               extra_headers = realloc(extra_headers, extra_headers_size);
+               extra_headers = xrealloc(extra_headers, extra_headers_size);
                extra_headers[extra_headers_size - len - 1] = 0;
                strcat(extra_headers, value);
                return 0;
@@ -381,7 +381,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                        continue;
 
                nr++;
-               list = realloc(list, nr * sizeof(list[0]));
+               list = xrealloc(list, nr * sizeof(list[0]));
                list[nr - 1] = commit;
        }
        total = nr;
index c0c8764f7fa71ffe459997f03b5158cd7c72209b..4d21d88412cac52cbd5d127de439abc3e172b352 100644 (file)
@@ -26,7 +26,7 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
                if (length > 0 && result[i][length - 1] == '/') {
                        char *without_slash = xmalloc(length);
                        memcpy(without_slash, result[i], length - 1);
-                       without_slash[length] = '\0';
+                       without_slash[length - 1] = '\0';
                        result[i] = without_slash;
                }
                if (base_name) {
@@ -114,7 +114,10 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        modes = xcalloc(count, sizeof(enum update_mode));
        dest_path = copy_pathspec(prefix, argv + argc - 1, 1, 0);
 
-       if (!lstat(dest_path[0], &st) &&
+       if (dest_path[0][0] == '\0')
+               /* special case: "." was normalized to "" */
+               destination = copy_pathspec(dest_path[0], argv + i, count, 1);
+       else if (!lstat(dest_path[0], &st) &&
                        S_ISDIR(st.st_mode)) {
                dest_path[0] = add_slash(dest_path[0]);
                destination = copy_pathspec(dest_path[0], argv + i, count, 1);
@@ -126,79 +129,71 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 
        /* Checking */
        for (i = 0; i < count; i++) {
-               int length;
+               const char *src = source[i], *dst = destination[i];
+               int length, src_is_dir;
                const char *bad = NULL;
 
                if (show_only)
-                       printf("Checking rename of '%s' to '%s'\n",
-                               source[i], destination[i]);
+                       printf("Checking rename of '%s' to '%s'\n", src, dst);
 
-               if (lstat(source[i], &st) < 0)
+               length = strlen(src);
+               if (lstat(src, &st) < 0)
                        bad = "bad source";
-
-               if (!bad &&
-                   (length = strlen(source[i])) >= 0 &&
-                   !strncmp(destination[i], source[i], length) &&
-                   (destination[i][length] == 0 || destination[i][length] == '/'))
+               else if (!strncmp(src, dst, length) &&
+                               (dst[length] == 0 || dst[length] == '/')) {
                        bad = "can not move directory into itself";
-
-               if (S_ISDIR(st.st_mode)) {
-                       const char *dir = source[i], *dest_dir = destination[i];
-                       int first, last, len = strlen(dir);
-
-                       if (lstat(dest_dir, &st) == 0) {
-                               bad = "cannot move directory over file";
-                               goto next;
-                       }
+               } else if ((src_is_dir = S_ISDIR(st.st_mode))
+                               && lstat(dst, &st) == 0)
+                       bad = "cannot move directory over file";
+               else if (src_is_dir) {
+                       int first, last;
 
                        modes[i] = WORKING_DIRECTORY;
 
-                       first = cache_name_pos(source[i], len);
+                       first = cache_name_pos(src, length);
                        if (first >= 0)
-                               die ("Huh? %s/ is in index?", dir);
+                               die ("Huh? %s/ is in index?", src);
 
                        first = -1 - first;
                        for (last = first; last < active_nr; last++) {
                                const char *path = active_cache[last]->name;
-                               if (strncmp(path, dir, len) || path[len] != '/')
+                               if (strncmp(path, src, length)
+                                               || path[length] != '/')
                                        break;
                        }
 
                        if (last - first < 1)
                                bad = "source directory is empty";
-                       else if (!bad) {
-                               int j, dst_len = strlen(dest_dir);
+                       else {
+                               int j, dst_len;
 
                                if (last - first > 0) {
-                                       source = realloc(source,
+                                       source = xrealloc(source,
                                                        (count + last - first)
                                                        * sizeof(char *));
-                                       destination = realloc(destination,
+                                       destination = xrealloc(destination,
                                                        (count + last - first)
                                                        * sizeof(char *));
-                                       modes = realloc(modes,
+                                       modes = xrealloc(modes,
                                                        (count + last - first)
                                                        * sizeof(enum update_mode));
                                }
 
-                               dest_dir = add_slash(dest_dir);
+                               dst = add_slash(dst);
+                               dst_len = strlen(dst) - 1;
 
                                for (j = 0; j < last - first; j++) {
                                        const char *path =
                                                active_cache[first + j]->name;
                                        source[count + j] = path;
                                        destination[count + j] =
-                                               prefix_path(dest_dir, dst_len,
-                                                       path + len);
+                                               prefix_path(dst, dst_len,
+                                                       path + length);
                                        modes[count + j] = INDEX;
                                }
                                count += last - first;
                        }
-
-                       goto next;
-               }
-
-               if (!bad && lstat(destination[i], &st) == 0) {
+               } else if (lstat(dst, &st) == 0) {
                        bad = "destination exists";
                        if (force) {
                                /*
@@ -210,24 +205,17 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                                        " will overwrite!\n",
                                                        bad);
                                        bad = NULL;
-                                       path_list_insert(destination[i],
-                                                       &overwritten);
+                                       path_list_insert(dst, &overwritten);
                                } else
                                        bad = "Cannot overwrite";
                        }
-               }
-
-               if (!bad && cache_name_pos(source[i], strlen(source[i])) < 0)
+               } else if (cache_name_pos(src, length) < 0)
                        bad = "not under version control";
+               else if (path_list_has_path(&src_for_dst, dst))
+                       bad = "multiple sources for the same target";
+               else
+                       path_list_insert(dst, &src_for_dst);
 
-               if (!bad) {
-                       if (path_list_has_path(&src_for_dst, destination[i]))
-                               bad = "multiple sources for the same target";
-                       else
-                               path_list_insert(destination[i], &src_for_dst);
-               }
-
-next:
                if (bad) {
                        if (ignore_errors) {
                                if (--count > 0) {
@@ -239,33 +227,32 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                }
                        } else
                                die ("%s, source=%s, destination=%s",
-                                    bad, source[i], destination[i]);
+                                    bad, src, dst);
                }
        }
 
        for (i = 0; i < count; i++) {
+               const char *src = source[i], *dst = destination[i];
+               enum update_mode mode = modes[i];
                if (show_only || verbose)
-                       printf("Renaming %s to %s\n",
-                              source[i], destination[i]);
-               if (!show_only && modes[i] != INDEX &&
-                   rename(source[i], destination[i]) < 0 &&
-                   !ignore_errors)
-                       die ("renaming %s failed: %s",
-                            source[i], strerror(errno));
-
-               if (modes[i] == WORKING_DIRECTORY)
+                       printf("Renaming %s to %s\n", src, dst);
+               if (!show_only && mode != INDEX &&
+                               rename(src, dst) < 0 && !ignore_errors)
+                       die ("renaming %s failed: %s", src, strerror(errno));
+
+               if (mode == WORKING_DIRECTORY)
                        continue;
 
-               if (cache_name_pos(source[i], strlen(source[i])) >= 0) {
-                       path_list_insert(source[i], &deleted);
+               if (cache_name_pos(src, strlen(src)) >= 0) {
+                       path_list_insert(src, &deleted);
 
                        /* destination can be a directory with 1 file inside */
-                       if (path_list_has_path(&overwritten, destination[i]))
-                               path_list_insert(destination[i], &changed);
+                       if (path_list_has_path(&overwritten, dst))
+                               path_list_insert(dst, &changed);
                        else
-                               path_list_insert(destination[i], &added);
+                               path_list_insert(dst, &added);
                } else
-                       path_list_insert(destination[i], &added);
+                       path_list_insert(dst, &added);
        }
 
         if (show_only) {
@@ -275,10 +262,10 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        } else {
                for (i = 0; i < changed.nr; i++) {
                        const char *path = changed.items[i].path;
-                       int i = cache_name_pos(path, strlen(path));
-                       struct cache_entry *ce = active_cache[i];
+                       int j = cache_name_pos(path, strlen(path));
+                       struct cache_entry *ce = active_cache[j];
 
-                       if (i < 0)
+                       if (j < 0)
                                die ("Huh? Cache entry for %s unknown?", path);
                        refresh_cache_entry(ce, 0);
                }
index 448461bc4826da8b34ebf32c876d9b2341f51447..46f524dfc32a5eaea06df6e3502c83710a1c09bb 100644 (file)
@@ -441,7 +441,7 @@ static int locate_object_entry_hash(const unsigned char *sha1)
        memcpy(&ui, sha1, sizeof(unsigned int));
        i = ui % object_ix_hashsz;
        while (0 < object_ix[i]) {
-               if (!memcmp(sha1, objects[object_ix[i]-1].sha1, 20))
+               if (!hashcmp(sha1, objects[object_ix[i] - 1].sha1))
                        return i;
                if (++i == object_ix_hashsz)
                        i = 0;
@@ -534,7 +534,7 @@ static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclud
        entry = objects + idx;
        nr_objects = idx + 1;
        memset(entry, 0, sizeof(*entry));
-       memcpy(entry->sha1, sha1, 20);
+       hashcpy(entry->sha1, sha1);
        entry->hash = hash;
 
        if (object_ix_hashsz * 3 <= nr_objects * 4)
@@ -607,7 +607,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
         */
        for (neigh = 0; neigh < 8; neigh++) {
                ent = pbase_tree_cache[my_ix];
-               if (ent && !memcmp(ent->sha1, sha1, 20)) {
+               if (ent && !hashcmp(ent->sha1, sha1)) {
                        ent->ref++;
                        return ent;
                }
@@ -649,7 +649,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
                free(ent->tree_data);
                nent = ent;
        }
-       memcpy(nent->sha1, sha1, 20);
+       hashcpy(nent->sha1, sha1);
        nent->tree_data = data;
        nent->tree_size = size;
        nent->ref = 1;
@@ -789,7 +789,7 @@ static void add_preferred_base(unsigned char *sha1)
                return;
 
        for (it = pbase_tree; it; it = it->next) {
-               if (!memcmp(it->pcache.sha1, tree_sha1, 20)) {
+               if (!hashcmp(it->pcache.sha1, tree_sha1)) {
                        free(data);
                        return;
                }
@@ -799,7 +799,7 @@ static void add_preferred_base(unsigned char *sha1)
        it->next = pbase_tree;
        pbase_tree = it;
 
-       memcpy(it->pcache.sha1, tree_sha1, 20);
+       hashcpy(it->pcache.sha1, tree_sha1);
        it->pcache.tree_data = data;
        it->pcache.tree_size = size;
 }
@@ -931,7 +931,7 @@ static struct object_entry **create_sorted_list(entry_sort_t sort)
 
 static int sha1_sort(const struct object_entry *a, const struct object_entry *b)
 {
-       return memcmp(a->sha1, b->sha1, 20);
+       return hashcmp(a->sha1, b->sha1);
 }
 
 static struct object_entry **create_final_object_list(void)
index 2b5e6fa9ed18c20cda264dbaf9df9d3cbac93c0e..ada8338cc1d0fbf389cd346b5134595afaaa2e66 100644 (file)
@@ -232,7 +232,7 @@ static int do_push(const char *repo)
        common_argc = argc;
 
        for (i = 0; i < n; i++) {
-               int error;
+               int err;
                int dest_argc = common_argc;
                int dest_refspec_nr = refspec_nr;
                const char **dest_refspec = refspec;
@@ -248,10 +248,10 @@ static int do_push(const char *repo)
                while (dest_refspec_nr--)
                        argv[dest_argc++] = *dest_refspec++;
                argv[dest_argc] = NULL;
-               error = run_command_v(argc, argv);
-               if (!error)
+               err = run_command_v(argc, argv);
+               if (!err)
                        continue;
-               switch (error) {
+               switch (err) {
                case -ERR_RUN_COMMAND_FORK:
                        die("unable to fork for %s", sender);
                case -ERR_RUN_COMMAND_EXEC:
@@ -262,7 +262,7 @@ static int do_push(const char *repo)
                case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
                        die("%s died with strange error", sender);
                default:
-                       return -error;
+                       return -err;
                }
        }
        return 0;
index 53087faf7a63e6268ffff5239142a00c120dcf8f..c1867d2a0052ad797481f3d5f9aa544952ff251b 100644 (file)
@@ -53,7 +53,7 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
        struct name_entry entry;
        int cnt;
 
-       memcpy(it->sha1, tree->object.sha1, 20);
+       hashcpy(it->sha1, tree->object.sha1);
        desc.buf = tree->buffer;
        desc.size = tree->size;
        cnt = 0;
index 95fbf77fad84a13330b0c0e58586edac0eb037f0..18786f88e3252dbd46d88014f2f35205c53d5200 100644 (file)
@@ -378,7 +378,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1)
        /* If both heads/foo and tags/foo exists, get_sha1 would
         * get confused.
         */
-       if (get_sha1(refname + ofs, tmp) || memcmp(tmp, sha1, 20))
+       if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
                ofs = 5;
        return append_ref(refname + ofs, sha1);
 }
@@ -442,7 +442,7 @@ static int rev_is_head(char *head_path, int headlen, char *name,
 {
        int namelen;
        if ((!head_path[0]) ||
-           (head_sha1 && sha1 && memcmp(head_sha1, sha1, 20)))
+           (head_sha1 && sha1 && hashcmp(head_sha1, sha1)))
                return 0;
        namelen = strlen(name);
        if ((headlen < namelen) ||
index 215892b6967ab3b42ef3826e3e934001de1f5162..61a413590d74d0fb167d715aa754df1a8794c085 100644 (file)
@@ -14,7 +14,7 @@
 #define BLOCKSIZE      (RECORDSIZE * 20)
 
 static const char tar_tree_usage[] =
-"git-tar-tree [--remote=<repo>] <ent> [basedir]";
+"git-tar-tree [--remote=<repo>] <tree-ish> [basedir]";
 
 static char block[BLOCKSIZE];
 static unsigned long offset;
@@ -22,30 +22,11 @@ static unsigned long offset;
 static time_t archive_time;
 static int tar_umask;
 
-/* tries hard to write, either succeeds or dies in the attempt */
-static void reliable_write(const void *data, unsigned long size)
-{
-       const char *buf = data;
-
-       while (size > 0) {
-               long ret = xwrite(1, buf, size);
-               if (ret < 0) {
-                       if (errno == EPIPE)
-                               exit(0);
-                       die("git-tar-tree: %s", strerror(errno));
-               } else if (!ret) {
-                       die("git-tar-tree: disk full?");
-               }
-               size -= ret;
-               buf += ret;
-       }
-}
-
 /* writes out the whole block, but only if it is full */
 static void write_if_needed(void)
 {
        if (offset == BLOCKSIZE) {
-               reliable_write(block, BLOCKSIZE);
+               write_or_die(1, block, BLOCKSIZE);
                offset = 0;
        }
 }
@@ -70,7 +51,7 @@ static void write_blocked(const void *data, unsigned long size)
                write_if_needed();
        }
        while (size >= BLOCKSIZE) {
-               reliable_write(buf, BLOCKSIZE);
+               write_or_die(1, buf, BLOCKSIZE);
                size -= BLOCKSIZE;
                buf += BLOCKSIZE;
        }
@@ -94,10 +75,10 @@ static void write_trailer(void)
 {
        int tail = BLOCKSIZE - offset;
        memset(block + offset, 0, tail);
-       reliable_write(block, BLOCKSIZE);
+       write_or_die(1, block, BLOCKSIZE);
        if (tail < 2 * RECORDSIZE) {
                memset(block, 0, offset);
-               reliable_write(block, BLOCKSIZE);
+               write_or_die(1, block, BLOCKSIZE);
        }
 }
 
@@ -294,7 +275,7 @@ static void traverse_tree(struct tree_desc *tree, struct strbuf *path)
        }
 }
 
-int git_tar_config(const char *var, const char *value)
+static int git_tar_config(const char *var, const char *value)
 {
        if (!strcmp(var, "tar.umask")) {
                if (!strcmp(value, "user")) {
index 63f4b8e45d1cb80042583fba382acc7f4f1f952c..ca0ebc258563f2ea2aec94eed2de31799f3f16cc 100644 (file)
@@ -95,7 +95,7 @@ static void add_delta_to_list(unsigned char *base_sha1, void *delta, unsigned lo
 {
        struct delta_info *info = xmalloc(sizeof(*info));
 
-       memcpy(info->base_sha1, base_sha1, 20);
+       hashcpy(info->base_sha1, base_sha1);
        info->size = size;
        info->delta = delta;
        info->next = delta_list;
@@ -136,7 +136,7 @@ static void added_object(unsigned char *sha1, const char *type, void *data, unsi
        struct delta_info *info;
 
        while ((info = *p) != NULL) {
-               if (!memcmp(info->base_sha1, sha1, 20)) {
+               if (!hashcmp(info->base_sha1, sha1)) {
                        *p = info->next;
                        p = &delta_list;
                        resolve_delta(type, data, size, info->delta, info->size);
@@ -173,7 +173,7 @@ static int unpack_delta_entry(unsigned long delta_size)
        unsigned char base_sha1[20];
        int result;
 
-       memcpy(base_sha1, fill(20), 20);
+       hashcpy(base_sha1, fill(20));
        use(20);
 
        delta_data = get_data(delta_size);
@@ -292,7 +292,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
        unpack_all();
        SHA1_Update(&ctx, buffer, offset);
        SHA1_Final(sha1, &ctx);
-       if (memcmp(fill(20), sha1, 20))
+       if (hashcmp(fill(20), sha1))
                die("final sha1 did not match");
        use(20);
 
index 9f0cf28ba2dde7c5000029107460a3f4ca873aa3..0620e779b04146a01f9e06cbbcd535b106034bd6 100644 (file)
@@ -142,7 +142,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
        size = cache_entry_size(len);
        ce = xcalloc(1, size);
 
-       memcpy(ce->sha1, sha1, 20);
+       hashcpy(ce->sha1, sha1);
        memcpy(ce->name, path, len);
        ce->ce_flags = create_ce_flags(len, stage);
        ce->ce_mode = create_ce_mode(mode);
@@ -306,7 +306,7 @@ static void read_index_info(int line_termination)
 }
 
 static const char update_index_usage[] =
-"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again] [--ignore-missing] [-z] [--verbose] [--] <file>...";
+"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
 
 static unsigned char head_sha1[20];
 static unsigned char merge_head_sha1[20];
@@ -333,7 +333,7 @@ static struct cache_entry *read_one_ent(const char *which,
        size = cache_entry_size(namelen);
        ce = xcalloc(1, size);
 
-       memcpy(ce->sha1, sha1, 20);
+       hashcpy(ce->sha1, sha1);
        memcpy(ce->name, path, namelen);
        ce->ce_flags = create_ce_flags(namelen, stage);
        ce->ce_mode = create_ce_mode(mode);
@@ -378,7 +378,7 @@ static int unresolve_one(const char *path)
                ret = -1;
                goto free_return;
        }
-       if (!memcmp(ce_2->sha1, ce_3->sha1, 20) &&
+       if (!hashcmp(ce_2->sha1, ce_3->sha1) &&
            ce_2->ce_mode == ce_3->ce_mode) {
                fprintf(stderr, "%s: identical in both, skipping.\n",
                        path);
@@ -460,7 +460,7 @@ static int do_reupdate(int ac, const char **av,
                        old = read_one_ent(NULL, head_sha1,
                                           ce->name, ce_namelen(ce), 0);
                if (old && ce->ce_mode == old->ce_mode &&
-                   !memcmp(ce->sha1, old->sha1, 20)) {
+                   !hashcmp(ce->sha1, old->sha1)) {
                        free(old);
                        continue; /* unchanged */
                }
@@ -595,7 +595,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                                        active_cache_changed = 0;
                                goto finish;
                        }
-                       if (!strcmp(path, "--again")) {
+                       if (!strcmp(path, "--again") || !strcmp(path, "-g")) {
                                has_errors = do_reupdate(argc - i, argv + i,
                                                         prefix, prefix_length);
                                if (has_errors)
index 5bd71825fdc48392952faf170efe98c072c7e482..90a3da53ad003a82781e6d4acfc7815c8f15f24f 100644 (file)
@@ -44,7 +44,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 
        if (get_sha1(value, sha1))
                die("%s: not a valid SHA1", value);
-       memset(oldsha1, 0, 20);
+       hashclr(oldsha1);
        if (oldval && get_sha1(oldval, oldsha1))
                die("%s: not a valid old SHA1", oldval);
 
index ca06149f186449407c6536fcc3caa37cd4101ce3..50670dc7bf46c74e95b2e204d05afc077350a19f 100644 (file)
@@ -50,10 +50,10 @@ int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)
        if (prefix) {
                struct cache_tree *subtree =
                        cache_tree_find(active_cache_tree, prefix);
-               memcpy(sha1, subtree->sha1, 20);
+               hashcpy(sha1, subtree->sha1);
        }
        else
-               memcpy(sha1, active_cache_tree->sha1, 20);
+               hashcpy(sha1, active_cache_tree->sha1);
 
        rollback_lock_file(lock_file);
 
diff --git a/builtin-zip-tree.c b/builtin-zip-tree.c
new file mode 100644 (file)
index 0000000..a5b834d
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2006 Rene Scharfe
+ */
+#include <time.h>
+#include "cache.h"
+#include "commit.h"
+#include "blob.h"
+#include "tree.h"
+#include "quote.h"
+#include "builtin.h"
+
+static const char zip_tree_usage[] =
+"git-zip-tree [-0|...|-9] <tree-ish> [ <base> ]";
+
+static int zip_date;
+static int zip_time;
+
+static unsigned char *zip_dir;
+static unsigned int zip_dir_size;
+
+static unsigned int zip_offset;
+static unsigned int zip_dir_offset;
+static unsigned int zip_dir_entries;
+
+#define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
+
+struct zip_local_header {
+       unsigned char magic[4];
+       unsigned char version[2];
+       unsigned char flags[2];
+       unsigned char compression_method[2];
+       unsigned char mtime[2];
+       unsigned char mdate[2];
+       unsigned char crc32[4];
+       unsigned char compressed_size[4];
+       unsigned char size[4];
+       unsigned char filename_length[2];
+       unsigned char extra_length[2];
+};
+
+struct zip_dir_header {
+       unsigned char magic[4];
+       unsigned char creator_version[2];
+       unsigned char version[2];
+       unsigned char flags[2];
+       unsigned char compression_method[2];
+       unsigned char mtime[2];
+       unsigned char mdate[2];
+       unsigned char crc32[4];
+       unsigned char compressed_size[4];
+       unsigned char size[4];
+       unsigned char filename_length[2];
+       unsigned char extra_length[2];
+       unsigned char comment_length[2];
+       unsigned char disk[2];
+       unsigned char attr1[2];
+       unsigned char attr2[4];
+       unsigned char offset[4];
+};
+
+struct zip_dir_trailer {
+       unsigned char magic[4];
+       unsigned char disk[2];
+       unsigned char directory_start_disk[2];
+       unsigned char entries_on_this_disk[2];
+       unsigned char entries[2];
+       unsigned char size[4];
+       unsigned char offset[4];
+       unsigned char comment_length[2];
+};
+
+static void copy_le16(unsigned char *dest, unsigned int n)
+{
+       dest[0] = 0xff & n;
+       dest[1] = 0xff & (n >> 010);
+}
+
+static void copy_le32(unsigned char *dest, unsigned int n)
+{
+       dest[0] = 0xff & n;
+       dest[1] = 0xff & (n >> 010);
+       dest[2] = 0xff & (n >> 020);
+       dest[3] = 0xff & (n >> 030);
+}
+
+static void *zlib_deflate(void *data, unsigned long size,
+                          unsigned long *compressed_size)
+{
+       z_stream stream;
+       unsigned long maxsize;
+       void *buffer;
+       int result;
+
+       memset(&stream, 0, sizeof(stream));
+       deflateInit(&stream, zlib_compression_level);
+       maxsize = deflateBound(&stream, size);
+       buffer = xmalloc(maxsize);
+
+       stream.next_in = data;
+       stream.avail_in = size;
+       stream.next_out = buffer;
+       stream.avail_out = maxsize;
+
+       do {
+               result = deflate(&stream, Z_FINISH);
+       } while (result == Z_OK);
+
+       if (result != Z_STREAM_END) {
+               free(buffer);
+               return NULL;
+       }
+
+       deflateEnd(&stream);
+       *compressed_size = stream.total_out;
+
+       return buffer;
+}
+
+static char *construct_path(const char *base, int baselen,
+                            const char *filename, int isdir, int *pathlen)
+{
+       int filenamelen = strlen(filename);
+       int len = baselen + filenamelen;
+       char *path, *p;
+
+       if (isdir)
+               len++;
+       p = path = xmalloc(len + 1);
+
+       memcpy(p, base, baselen);
+       p += baselen;
+       memcpy(p, filename, filenamelen);
+       p += filenamelen;
+       if (isdir)
+               *p++ = '/';
+       *p = '\0';
+
+       *pathlen = len;
+
+       return path;
+}
+
+static int write_zip_entry(const unsigned char *sha1,
+                           const char *base, int baselen,
+                           const char *filename, unsigned mode, int stage)
+{
+       struct zip_local_header header;
+       struct zip_dir_header dirent;
+       unsigned long compressed_size;
+       unsigned long uncompressed_size;
+       unsigned long crc;
+       unsigned long direntsize;
+       unsigned long size;
+       int method;
+       int result = -1;
+       int pathlen;
+       unsigned char *out;
+       char *path;
+       char type[20];
+       void *buffer = NULL;
+       void *deflated = NULL;
+
+       crc = crc32(0, Z_NULL, 0);
+
+       path = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen);
+       if (pathlen > 0xffff) {
+               error("path too long (%d chars, SHA1: %s): %s", pathlen,
+                     sha1_to_hex(sha1), path);
+               goto out;
+       }
+
+       if (S_ISDIR(mode)) {
+               method = 0;
+               result = READ_TREE_RECURSIVE;
+               out = NULL;
+               uncompressed_size = 0;
+               compressed_size = 0;
+       } else if (S_ISREG(mode)) {
+               method = zlib_compression_level == 0 ? 0 : 8;
+               result = 0;
+               buffer = read_sha1_file(sha1, type, &size);
+               if (!buffer)
+                       die("cannot read %s", sha1_to_hex(sha1));
+               crc = crc32(crc, buffer, size);
+               out = buffer;
+               uncompressed_size = size;
+               compressed_size = size;
+       } else {
+               error("unsupported file mode: 0%o (SHA1: %s)", mode,
+                     sha1_to_hex(sha1));
+               goto out;
+       }
+
+       if (method == 8) {
+               deflated = zlib_deflate(buffer, size, &compressed_size);
+               if (deflated && compressed_size - 6 < size) {
+                       /* ZLIB --> raw compressed data (see RFC 1950) */
+                       /* CMF and FLG ... */
+                       out = (unsigned char *)deflated + 2;
+                       compressed_size -= 6;   /* ... and ADLER32 */
+               } else {
+                       method = 0;
+                       compressed_size = size;
+               }
+       }
+
+       /* make sure we have enough free space in the dictionary */
+       direntsize = sizeof(struct zip_dir_header) + pathlen;
+       while (zip_dir_size < zip_dir_offset + direntsize) {
+               zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
+               zip_dir = xrealloc(zip_dir, zip_dir_size);
+       }
+
+       copy_le32(dirent.magic, 0x02014b50);
+       copy_le16(dirent.creator_version, 0);
+       copy_le16(dirent.version, 20);
+       copy_le16(dirent.flags, 0);
+       copy_le16(dirent.compression_method, method);
+       copy_le16(dirent.mtime, zip_time);
+       copy_le16(dirent.mdate, zip_date);
+       copy_le32(dirent.crc32, crc);
+       copy_le32(dirent.compressed_size, compressed_size);
+       copy_le32(dirent.size, uncompressed_size);
+       copy_le16(dirent.filename_length, pathlen);
+       copy_le16(dirent.extra_length, 0);
+       copy_le16(dirent.comment_length, 0);
+       copy_le16(dirent.disk, 0);
+       copy_le16(dirent.attr1, 0);
+       copy_le32(dirent.attr2, 0);
+       copy_le32(dirent.offset, zip_offset);
+       memcpy(zip_dir + zip_dir_offset, &dirent, sizeof(struct zip_dir_header));
+       zip_dir_offset += sizeof(struct zip_dir_header);
+       memcpy(zip_dir + zip_dir_offset, path, pathlen);
+       zip_dir_offset += pathlen;
+       zip_dir_entries++;
+
+       copy_le32(header.magic, 0x04034b50);
+       copy_le16(header.version, 20);
+       copy_le16(header.flags, 0);
+       copy_le16(header.compression_method, method);
+       copy_le16(header.mtime, zip_time);
+       copy_le16(header.mdate, zip_date);
+       copy_le32(header.crc32, crc);
+       copy_le32(header.compressed_size, compressed_size);
+       copy_le32(header.size, uncompressed_size);
+       copy_le16(header.filename_length, pathlen);
+       copy_le16(header.extra_length, 0);
+       write_or_die(1, &header, sizeof(struct zip_local_header));
+       zip_offset += sizeof(struct zip_local_header);
+       write_or_die(1, path, pathlen);
+       zip_offset += pathlen;
+       if (compressed_size > 0) {
+               write_or_die(1, out, compressed_size);
+               zip_offset += compressed_size;
+       }
+
+out:
+       free(buffer);
+       free(deflated);
+       free(path);
+
+       return result;
+}
+
+static void write_zip_trailer(const unsigned char *sha1)
+{
+       struct zip_dir_trailer trailer;
+
+       copy_le32(trailer.magic, 0x06054b50);
+       copy_le16(trailer.disk, 0);
+       copy_le16(trailer.directory_start_disk, 0);
+       copy_le16(trailer.entries_on_this_disk, zip_dir_entries);
+       copy_le16(trailer.entries, zip_dir_entries);
+       copy_le32(trailer.size, zip_dir_offset);
+       copy_le32(trailer.offset, zip_offset);
+       copy_le16(trailer.comment_length, sha1 ? 40 : 0);
+
+       write_or_die(1, zip_dir, zip_dir_offset);
+       write_or_die(1, &trailer, sizeof(struct zip_dir_trailer));
+       if (sha1)
+               write_or_die(1, sha1_to_hex(sha1), 40);
+}
+
+static void dos_time(time_t *time, int *dos_date, int *dos_time)
+{
+       struct tm *t = localtime(time);
+
+       *dos_date = t->tm_mday + (t->tm_mon + 1) * 32 +
+                   (t->tm_year + 1900 - 1980) * 512;
+       *dos_time = t->tm_sec / 2 + t->tm_min * 32 + t->tm_hour * 2048;
+}
+
+int cmd_zip_tree(int argc, const char **argv, const char *prefix)
+{
+       unsigned char sha1[20];
+       struct tree *tree;
+       struct commit *commit;
+       time_t archive_time;
+       char *base;
+       int baselen;
+
+       git_config(git_default_config);
+
+       if (argc > 1 && argv[1][0] == '-') {
+               if (isdigit(argv[1][1]) && argv[1][2] == '\0') {
+                       zlib_compression_level = argv[1][1] - '0';
+                       argc--;
+                       argv++;
+               }
+       }
+
+       switch (argc) {
+       case 3:
+               base = strdup(argv[2]);
+               baselen = strlen(base);
+               break;
+       case 2:
+               base = strdup("");
+               baselen = 0;
+               break;
+       default:
+               usage(zip_tree_usage);
+       }
+
+       if (get_sha1(argv[1], sha1))
+               die("Not a valid object name %s", argv[1]);
+
+       commit = lookup_commit_reference_gently(sha1, 1);
+       archive_time = commit ? commit->date : time(NULL);
+       dos_time(&archive_time, &zip_date, &zip_time);
+
+       zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
+       zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
+
+       tree = parse_tree_indirect(sha1);
+       if (!tree)
+               die("not a tree object");
+
+       if (baselen > 0) {
+               write_zip_entry(tree->object.sha1, "", 0, base, 040777, 0);
+               base = xrealloc(base, baselen + 1);
+               base[baselen] = '/';
+               baselen++;
+               base[baselen] = '\0';
+       }
+       read_tree_recursive(tree, base, baselen, 0, NULL, write_zip_entry);
+       write_zip_trailer(commit ? commit->object.sha1 : NULL);
+
+       free(zip_dir);
+       free(base);
+
+       return 0;
+}
index ade58c4a1f06b161f00caa015192fa89c137d273..25431d70816634cec4ca6c54dc670ac536246277 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -52,6 +52,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
+extern int cmd_zip_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
 extern int cmd_update_index(int argc, const char **argv, const char *prefix);
 extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
index d9f7e1e3dd598d34e08d6370544b562daf4640d2..323c68a6709f30312e0dfb0fd60fcd7e69cd710b 100644 (file)
@@ -335,7 +335,7 @@ static int update_one(struct cache_tree *it,
                offset += sprintf(buffer + offset,
                                  "%o %.*s", mode, entlen, path + baselen);
                buffer[offset++] = 0;
-               memcpy(buffer + offset, sha1, 20);
+               hashcpy((unsigned char*)buffer + offset, sha1);
                offset += 20;
 
 #if DEBUG
@@ -412,7 +412,7 @@ static void *write_one(struct cache_tree *it,
 #endif
 
        if (0 <= it->entry_count) {
-               memcpy(buffer + *offset, it->sha1, 20);
+               hashcpy((unsigned char*)buffer + *offset, it->sha1);
                *offset += 20;
        }
        for (i = 0; i < it->subtree_nr; i++) {
@@ -478,7 +478,7 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
        if (0 <= it->entry_count) {
                if (size < 20)
                        goto free_return;
-               memcpy(it->sha1, buf, 20);
+               hashcpy(it->sha1, (unsigned char*)buf);
                buf += 20;
                size -= 20;
        }
diff --git a/cache.h b/cache.h
index c7382996f62061f1022262fcc6e6f3f15e946d0a..ccb83a1fd5ccf9fe38e154b93b436e0021a91be6 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -123,7 +123,7 @@ extern int cache_errno;
 #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
 #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
 
-extern char *get_git_dir(void);
+extern const char *get_git_dir(void);
 extern char *get_object_directory(void);
 extern char *get_refs_directory(void);
 extern char *get_index_file(void);
@@ -214,6 +214,18 @@ static inline int is_null_sha1(const unsigned char *sha1)
 {
        return !memcmp(sha1, null_sha1, 20);
 }
+static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
+{
+       return memcmp(sha1, sha2, 20);
+}
+static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src)
+{
+       memcpy(sha_dst, sha_src, 20);
+}
+static inline void hashclr(unsigned char *hash)
+{
+       memset(hash, 0, 20);
+}
 
 int git_mkstemp(char *path, size_t n, const char *template);
 
@@ -274,7 +286,7 @@ extern void *read_object_with_reference(const unsigned char *sha1,
                                        unsigned long *size,
                                        unsigned char *sha1_ret);
 
-const char *show_date(unsigned long time, int timezone);
+const char *show_date(unsigned long time, int timezone, int relative);
 const char *show_rfc2822_date(unsigned long time, int timezone);
 int parse_date(const char *date, char *buf, int bufsize);
 void datestamp(char *buf, int bufsize);
@@ -384,6 +396,7 @@ extern char git_default_name[MAX_GITNAME];
 extern char git_commit_encoding[MAX_ENCODING_LENGTH];
 
 extern int copy_fd(int ifd, int ofd);
+extern void write_or_die(int fd, const void *buf, size_t count);
 
 /* Finish off pack transfer receiving end */
 extern int receive_unpack_pack(int fd[2], const char *me, int quiet, int);
index ce063b4ffa48eb1db8849d5aabb6732fc98946b6..46d9121baf2ebb024f6b19993a9b75fa3b67951a 100644 (file)
@@ -31,9 +31,9 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
                        memset(p->parent, 0,
                               sizeof(p->parent[0]) * num_parent);
 
-                       memcpy(p->sha1, q->queue[i]->two->sha1, 20);
+                       hashcpy(p->sha1, q->queue[i]->two->sha1);
                        p->mode = q->queue[i]->two->mode;
-                       memcpy(p->parent[n].sha1, q->queue[i]->one->sha1, 20);
+                       hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1);
                        p->parent[n].mode = q->queue[i]->one->mode;
                        p->parent[n].status = q->queue[i]->status;
                        *tail = p;
@@ -56,8 +56,7 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
                        len = strlen(path);
                        if (len == p->len && !memcmp(path, p->path, len)) {
                                found = 1;
-                               memcpy(p->parent[n].sha1,
-                                      q->queue[i]->one->sha1, 20);
+                               hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1);
                                p->parent[n].mode = q->queue[i]->one->mode;
                                p->parent[n].status = q->queue[i]->status;
                                break;
@@ -688,8 +687,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
        for (i = 0; i < num_parent; i++) {
                int j;
                for (j = 0; j < i; j++) {
-                       if (!memcmp(elem->parent[i].sha1,
-                                   elem->parent[j].sha1, 20)) {
+                       if (!hashcmp(elem->parent[i].sha1,
+                                    elem->parent[j].sha1)) {
                                reuse_combine_diff(sline, cnt, i, j);
                                break;
                        }
@@ -927,6 +926,7 @@ void diff_tree_combined_merge(const unsigned char *sha1,
        for (parents = commit->parents, num_parent = 0;
             parents;
             parents = parents->next, num_parent++)
-               memcpy(parent + num_parent, parents->item->object.sha1, 20);
+               hashcpy((unsigned char*)(parent + num_parent),
+                       parents->item->object.sha1);
        diff_tree_combined(sha1, parent, num_parent, dense, rev);
 }
index 972d1b70c02d0a21bbb187ef964e6604d4556e87..c3ff9b4175c00a600ae25f9dc90eb521d7053719 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -7,15 +7,15 @@ int save_commit_buffer = 1;
 struct sort_node
 {
        /*
-         * the number of children of the associated commit
-         * that also occur in the list being sorted.
-         */
+        * the number of children of the associated commit
+        * that also occur in the list being sorted.
+        */
        unsigned int indegree;
 
        /*
-         * reference to original list item that we will re-use
-         * on output.
-         */
+        * reference to original list item that we will re-use
+        * on output.
+        */
        struct commit_list * list_item;
 
 };
@@ -123,7 +123,7 @@ static int commit_graft_pos(const unsigned char *sha1)
        while (lo < hi) {
                int mi = (lo + hi) / 2;
                struct commit_graft *graft = commit_graft[mi];
-               int cmp = memcmp(sha1, graft->sha1, 20);
+               int cmp = hashcmp(sha1, graft->sha1);
                if (!cmp)
                        return mi;
                if (cmp < 0)
@@ -507,14 +507,14 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c
        }
        switch (fmt) {
        case CMIT_FMT_MEDIUM:
-               ret += sprintf(buf + ret, "Date:   %s\n", show_date(time, tz));
+               ret += sprintf(buf + ret, "Date:   %s\n", show_date(time, tz, 0));
                break;
        case CMIT_FMT_EMAIL:
                ret += sprintf(buf + ret, "Date: %s\n",
                               show_rfc2822_date(time, tz));
                break;
        case CMIT_FMT_FULLER:
-               ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz));
+               ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz, 0));
                break;
        default:
                /* notin' */
index 7a6a73f2a333d067c5a5442004f76ebbb9aaed17..e501ccce259e7ac1a4e92fecc713950e82d3b71a 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -77,7 +77,7 @@ struct ref **get_remote_heads(int in, struct ref **list,
                if (nr_match && !path_match(name, nr_match, match))
                        continue;
                ref = xcalloc(1, sizeof(*ref) + len - 40);
-               memcpy(ref->old_sha1, old_sha1, 20);
+               hashcpy(ref->old_sha1, old_sha1);
                memcpy(ref->name, buffer + 41, len - 40);
                *list = ref;
                list = &ref->next;
@@ -208,7 +208,7 @@ static struct ref *try_explicit_object_name(const char *name)
        len = strlen(name) + 1;
        ref = xcalloc(1, sizeof(*ref) + len);
        memcpy(ref->name, name, len);
-       memcpy(ref->new_sha1, sha1, 20);
+       hashcpy(ref->new_sha1, sha1);
        return ref;
 }
 
@@ -318,7 +318,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
                        int len = strlen(src->name) + 1;
                        dst_peer = xcalloc(1, sizeof(*dst_peer) + len);
                        memcpy(dst_peer->name, src->name, len);
-                       memcpy(dst_peer->new_sha1, src->new_sha1, 20);
+                       hashcpy(dst_peer->new_sha1, src->new_sha1);
                        link_dst_tail(dst_peer, dst_tail);
                }
                dst_peer->peer_ref = src;
index 6924df286e0a85bd49ef69e29781658ba8a17339..77c29de305fabc518edf060b0e6634d9c5c9f71e 100644 (file)
@@ -7,40 +7,50 @@ gitview - A GTK based repository browser for git
 
 SYNOPSIS
 --------
-'gitview'  [options] [args]
+'gitview' [options] [args]
 
 DESCRIPTION
 ---------
 
-Dependencies
+Dependencies:
 
 * Python 2.4
 * PyGTK 2.8 or later
 * PyCairo 1.0 or later
 
 OPTIONS
-------
-       --without-diff
-               If the user doesn't want to list the commit diffs in the main window. This may speed up the repository browsing.
-
-       <args>
-               All the valid option for git-rev-list(1)
-       Key Bindings:
-       F4:
-               To maximize the window
-       F5:
-               To reread references.
-       F11:
-               Full screen
-       F12:
-               Leave full screen
+-------
+--without-diff::
+
+       If the user doesn't want to list the commit diffs in the main window.
+       This may speed up the repository browsing.
+
+<args>::
+
+       All the valid option for gitlink:git-rev-list[1].
+
+Key Bindings
+------------
+F4::
+       To maximize the window
+
+F5::
+       To reread references.
+
+F11::
+       Full screen
+
+F12::
+       Leave full screen
 
 EXAMPLES
-------
-       gitview v2.6.12.. include/scsi drivers/scsi
-         Show as the changes since version v2.6.12 that changed any file in the include/scsi
-         or drivers/scsi subdirectories
+--------
+
+gitview v2.6.12.. include/scsi drivers/scsi::
+
+       Show as the changes since version v2.6.12 that changed any file in the
+       include/scsi or drivers/scsi subdirectories
 
-       gitview --since=2.weeks.ago
-         Show the changes during the last two weeks
+gitview --since=2.weeks.ago::
 
+       Show the changes during the last two weeks
index 168771ed857dd9e95b1e14da40f1e39d18f7b2cf..631678b08a7cb83b0349f1a683d3cd7fb797fb7a 100644 (file)
@@ -23,7 +23,7 @@ static struct entry * convert_entry(unsigned char *sha1);
 static struct entry *insert_new(unsigned char *sha1, int pos)
 {
        struct entry *new = xcalloc(1, sizeof(struct entry));
-       memcpy(new->old_sha1, sha1, 20);
+       hashcpy(new->old_sha1, sha1);
        memmove(convert + pos + 1, convert + pos, (nr_convert - pos) * sizeof(struct entry *));
        convert[pos] = new;
        nr_convert++;
@@ -39,7 +39,7 @@ static struct entry *lookup_entry(unsigned char *sha1)
        while (low < high) {
                int next = (low + high) / 2;
                struct entry *n = convert[next];
-               int cmp = memcmp(sha1, n->old_sha1, 20);
+               int cmp = hashcmp(sha1, n->old_sha1);
                if (!cmp)
                        return n;
                if (cmp < 0) {
@@ -54,7 +54,7 @@ static struct entry *lookup_entry(unsigned char *sha1)
 static void convert_binary_sha1(void *buffer)
 {
        struct entry *entry = convert_entry(buffer);
-       memcpy(buffer, entry->new_sha1, 20);
+       hashcpy(buffer, entry->new_sha1);
 }
 
 static void convert_ascii_sha1(void *buffer)
@@ -104,7 +104,7 @@ static int write_subdirectory(void *buffer, unsigned long size, const char *base
                if (!slash) {
                        newlen += sprintf(new + newlen, "%o %s", mode, path);
                        new[newlen++] = '\0';
-                       memcpy(new + newlen, (char *) buffer + len - 20, 20);
+                       hashcpy((unsigned char*)new + newlen, (unsigned char *) buffer + len - 20);
                        newlen += 20;
 
                        used += len;
index e2278897d08b750f383ae5bb2ac7e738a99a7ae5..b7174c6c056c5a8f2a800ecbcb3cdf304c0bfc3f 100644 (file)
@@ -38,7 +38,7 @@ int sha1close(struct sha1file *f, unsigned char *result, int update)
        }
        SHA1_Final(f->buffer, &f->ctx);
        if (result)
-               memcpy(result, f->buffer, 20);
+               hashcpy(result, f->buffer);
        if (update)
                sha1flush(f, 20);
        if (close(f->fd))
index 012936f3bd76d9f9648ba9498b4126c7d6861e5c..5bf5c82627beb8d8a5af71bce55c7e850ea54c46 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -526,7 +526,6 @@ static int socksetup(int port, int **socklist_p)
 
        for (ai = ai0; ai; ai = ai->ai_next) {
                int sockfd;
-               int *newlist;
 
                sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
                if (sockfd < 0)
@@ -560,11 +559,7 @@ static int socksetup(int port, int **socklist_p)
                        continue;       /* not fatal */
                }
 
-               newlist = realloc(socklist, sizeof(int) * (socknum + 1));
-               if (!newlist)
-                       die("memory allocation failed: %s", strerror(errno));
-
-               socklist = newlist;
+               socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
                socklist[socknum++] = sockfd;
 
                if (maxfd < sockfd)
diff --git a/date.c b/date.c
index 66be23ab21ef855ecbadeceae1dea2972efd4c2f..e387dcd3976d8e12afdce5d7600ca0022f4ca835 100644 (file)
--- a/date.c
+++ b/date.c
@@ -37,6 +37,16 @@ static const char *weekday_names[] = {
        "Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"
 };
 
+static time_t gm_time_t(unsigned long time, int tz)
+{
+       int minutes;
+
+       minutes = tz < 0 ? -tz : tz;
+       minutes = (minutes / 100)*60 + (minutes % 100);
+       minutes = tz < 0 ? -minutes : minutes;
+       return time + minutes * 60;
+}
+
 /*
  * The "tz" thing is passed in as this strange "decimal parse of tz"
  * thing, which means that tz -0100 is passed in as the integer -100,
@@ -44,21 +54,58 @@ static const char *weekday_names[] = {
  */
 static struct tm *time_to_tm(unsigned long time, int tz)
 {
-       time_t t;
-       int minutes;
-
-       minutes = tz < 0 ? -tz : tz;
-       minutes = (minutes / 100)*60 + (minutes % 100);
-       minutes = tz < 0 ? -minutes : minutes;
-       t = time + minutes * 60;
+       time_t t = gm_time_t(time, tz);
        return gmtime(&t);
 }
 
-const char *show_date(unsigned long time, int tz)
+const char *show_date(unsigned long time, int tz, int relative)
 {
        struct tm *tm;
        static char timebuf[200];
 
+       if (relative) {
+               unsigned long diff;
+               time_t t = gm_time_t(time, tz);
+               struct timeval now;
+               gettimeofday(&now, NULL);
+               if (now.tv_sec < t)
+                       return "in the future";
+               diff = now.tv_sec - t;
+               if (diff < 90) {
+                       snprintf(timebuf, sizeof(timebuf), "%lu seconds ago", diff);
+                       return timebuf;
+               }
+               /* Turn it into minutes */
+               diff = (diff + 30) / 60;
+               if (diff < 90) {
+                       snprintf(timebuf, sizeof(timebuf), "%lu minutes ago", diff);
+                       return timebuf;
+               }
+               /* Turn it into hours */
+               diff = (diff + 30) / 60;
+               if (diff < 36) {
+                       snprintf(timebuf, sizeof(timebuf), "%lu hours ago", diff);
+                       return timebuf;
+               }
+               /* We deal with number of days from here on */
+               diff = (diff + 12) / 24;
+               if (diff < 14) {
+                       snprintf(timebuf, sizeof(timebuf), "%lu days ago", diff);
+                       return timebuf;
+               }
+               /* Say weeks for the past 10 weeks or so */
+               if (diff < 70) {
+                       snprintf(timebuf, sizeof(timebuf), "%lu weeks ago", (diff + 3) / 7);
+                       return timebuf;
+               }
+               /* Say months for the past 12 months or so */
+               if (diff < 360) {
+                       snprintf(timebuf, sizeof(timebuf), "%lu months ago", (diff + 15) / 30);
+                       return timebuf;
+               }
+               /* Else fall back on absolute format.. */
+       }
+
        tm = time_to_tm(time, tz);
        if (!tm)
                return NULL;
@@ -584,10 +631,10 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, int *num)
        const struct typelen *tl;
        const struct special *s;
        const char *end = date;
-       int n = 1, i;
+       int i;
 
-       while (isalpha(*++end))
-               n++;
+       while (isalpha(*++end));
+               ;
 
        for (i = 0; i < 12; i++) {
                int match = match_string(date, month_names[i]);
index 2b9301fc1205795e30dfd7a7493cb03cdebdb437..5dd8b2e3977a2ff724ca208621f76a898cff0389 100644 (file)
@@ -42,7 +42,7 @@ static void add_to_known_names(const char *path,
        struct commit_name *name = xmalloc(sizeof(struct commit_name) + len);
 
        name->commit = commit;
-       name->prio = prio; 
+       name->prio = prio;
        memcpy(name->path, path, len);
        idx = names;
        if (idx >= allocs) {
@@ -154,7 +154,7 @@ int main(int argc, char **argv)
                        tags = 1;
                else if (!strncmp(arg, "--abbrev=", 9)) {
                        abbrev = strtoul(arg + 9, NULL, 10);
-                       if (abbrev < MINIMUM_ABBREV || 40 <= abbrev)
+                       if (abbrev < MINIMUM_ABBREV || 40 < abbrev)
                                abbrev = DEFAULT_ABBREV;
                }
                else
index 7da9205a5da6a4f016bc6b556bee01895cdcc19d..fa16d06c8d1e85a458428c673cb2f589857f5424 100644 (file)
@@ -152,7 +152,7 @@ struct delta_index * create_delta_index(const void *buf, unsigned long bufsize)
           initialization in create_delta(). */
        entries = (bufsize - 1)  / RABIN_WINDOW;
        hsize = entries / 4;
-       for (i = 4; (1 << i) < hsize && i < 31; i++);
+       for (i = 4; (1u << i) < hsize && i < 31; i++);
        hsize = 1 << i;
        hmask = hsize - 1;
 
@@ -392,7 +392,7 @@ create_delta(const struct delta_index *index,
                                outsize = max_size + MAX_OP_SIZE + 1;
                        if (max_size && outpos > max_size)
                                break;
-                       out = realloc(out, outsize);
+                       out = xrealloc(out, outsize);
                        if (!out) {
                                free(tmp);
                                return NULL;
index 116b5a9d6834c9517ccc2202510b37a1e1d863a5..9edfa9262622c64edecfaf7b4f72a79873b8882a 100644 (file)
@@ -48,7 +48,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                        memcpy(dpath->path, ce->name, path_len);
                        dpath->path[path_len] = '\0';
                        dpath->mode = 0;
-                       memset(dpath->sha1, 0, 20);
+                       hashclr(dpath->sha1);
                        memset(&(dpath->parent[0]), 0,
                                        sizeof(struct combine_diff_parent)*5);
 
@@ -66,8 +66,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                                if (2 <= stage) {
                                        int mode = ntohl(nce->ce_mode);
                                        num_compare_stages++;
-                                       memcpy(dpath->parent[stage-2].sha1,
-                                              nce->sha1, 20);
+                                       hashcpy(dpath->parent[stage-2].sha1, nce->sha1);
                                        dpath->parent[stage-2].mode =
                                                canon_mode(mode);
                                        dpath->parent[stage-2].status =
@@ -215,7 +214,7 @@ static int show_modified(struct rev_info *revs,
        }
 
        oldmode = old->ce_mode;
-       if (mode == oldmode && !memcmp(sha1, old->sha1, 20) &&
+       if (mode == oldmode && !hashcmp(sha1, old->sha1) &&
            !revs->diffopt.find_copies_harder)
                return 0;
 
diff --git a/diff.c b/diff.c
index b8161960e6dbee0b8ad13bd1f34bfc843c69c8f5..70699fd8c48754215934a8ed45db336b9db68918 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1107,7 +1107,7 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
 {
        if (mode) {
                spec->mode = canon_mode(mode);
-               memcpy(spec->sha1, sha1, 20);
+               hashcpy(spec->sha1, sha1);
                spec->sha1_valid = !is_null_sha1(sha1);
        }
 }
@@ -1146,7 +1146,7 @@ static int work_tree_matches(const char *name, const unsigned char *sha1)
        if ((lstat(name, &st) < 0) ||
            !S_ISREG(st.st_mode) || /* careful! */
            ce_match_stat(ce, &st, 0) ||
-           memcmp(sha1, ce->sha1, 20))
+           hashcmp(sha1, ce->sha1))
                return 0;
        /* we return 1 only when we can stat, it is a regular file,
         * stat information matches, and sha1 recorded in the cache
@@ -1174,7 +1174,7 @@ static struct sha1_size_cache *locate_size_cache(unsigned char *sha1,
        while (last > first) {
                int cmp, next = (last + first) >> 1;
                e = sha1_size_cache[next];
-               cmp = memcmp(e->sha1, sha1, 20);
+               cmp = hashcmp(e->sha1, sha1);
                if (!cmp)
                        return e;
                if (cmp < 0) {
@@ -1200,7 +1200,7 @@ static struct sha1_size_cache *locate_size_cache(unsigned char *sha1,
                        sizeof(*sha1_size_cache));
        e = xmalloc(sizeof(struct sha1_size_cache));
        sha1_size_cache[first] = e;
-       memcpy(e->sha1, sha1, 20);
+       hashcpy(e->sha1, sha1);
        e->size = size;
        return e;
 }
@@ -1522,7 +1522,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
                }
        }
        else
-               memset(one->sha1, 0, 20);
+               hashclr(one->sha1);
 }
 
 static void run_diff(struct diff_filepair *p, struct diff_options *o)
@@ -1585,7 +1585,7 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
                ;
        }
 
-       if (memcmp(one->sha1, two->sha1, 20)) {
+       if (hashcmp(one->sha1, two->sha1)) {
                int abbrev = o->full_index ? 40 : DEFAULT_ABBREV;
 
                len += snprintf(msg + len, sizeof(msg) - len,
@@ -2104,7 +2104,7 @@ int diff_unmodified_pair(struct diff_filepair *p)
         * dealing with a change.
         */
        if (one->sha1_valid && two->sha1_valid &&
-           !memcmp(one->sha1, two->sha1, sizeof(one->sha1)))
+           !hashcmp(one->sha1, two->sha1))
                return 1; /* no change */
        if (!one->sha1_valid && !two->sha1_valid)
                return 1; /* both look at the same file on the filesystem. */
@@ -2243,7 +2243,7 @@ static void diff_resolve_rename_copy(void)
                        if (!p->status)
                                p->status = DIFF_STATUS_RENAMED;
                }
-               else if (memcmp(p->one->sha1, p->two->sha1, 20) ||
+               else if (hashcmp(p->one->sha1, p->two->sha1) ||
                         p->one->mode != p->two->mode)
                        p->status = DIFF_STATUS_MODIFIED;
                else {
index ed0e14c6d8b1b8347f20c890854972be6c6a234c..acb18db1db27dc29fdb76bd519174aa56f56121d 100644 (file)
@@ -56,7 +56,7 @@ static int should_break(struct diff_filespec *src,
                return 0; /* leave symlink rename alone */
 
        if (src->sha1_valid && dst->sha1_valid &&
-           !memcmp(src->sha1, dst->sha1, 20))
+           !hashcmp(src->sha1, dst->sha1))
                return 0; /* they are the same */
 
        if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
index 0ec488a9033ea2d4514dab450d9e20581782ddbb..ef239012b65c901bba5eef598f62679fd288106e 100644 (file)
@@ -101,7 +101,7 @@ static int is_exact_match(struct diff_filespec *src,
                          int contents_too)
 {
        if (src->sha1_valid && dst->sha1_valid &&
-           !memcmp(src->sha1, dst->sha1, 20))
+           !hashcmp(src->sha1, dst->sha1))
                return 1;
        if (!contents_too)
                return 0;
diff --git a/dir.c b/dir.c
index 092d07736c60d4c6d86201ebeb841498c3be92a0..d53d48f70c7f07a3fe5e6851467fc566b341aeb9 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -101,8 +101,8 @@ void add_exclude(const char *string, const char *base,
        x->baselen = baselen;
        if (which->nr == which->alloc) {
                which->alloc = alloc_nr(which->alloc);
-               which->excludes = realloc(which->excludes,
-                                         which->alloc * sizeof(x));
+               which->excludes = xrealloc(which->excludes,
+                                          which->alloc * sizeof(x));
        }
        which->excludes[which->nr++] = x;
 }
@@ -293,7 +293,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
        if (fdir) {
                int exclude_stk;
                struct dirent *de;
-               char fullname[MAXPATHLEN + 1];
+               char fullname[PATH_MAX + 1];
                memcpy(fullname, base, baselen);
 
                exclude_stk = push_exclude_per_directory(dir, base, baselen);
index 1ccaf5177318f8765205e192abdffc3336c9aacb..1f73f1ea7dfa6a14dedf384c99751e86c8121ff4 100644 (file)
@@ -33,7 +33,7 @@ static int dump_cache_tree(struct cache_tree *it,
        }
        else {
                dump_one(it, pfx, "");
-               if (memcmp(it->sha1, ref->sha1, 20) ||
+               if (hashcmp(it->sha1, ref->sha1) ||
                    ref->entry_count != it->entry_count ||
                    ref->subtree_nr != it->subtree_nr) {
                        dump_one(ref, pfx, "#(ref) ");
diff --git a/entry.c b/entry.c
index 793724fd52063157545f523f6d88953b96385c2c..b2ea0efa82e1a0511fe5aa798618c23827b59bab 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -135,7 +135,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
 
 int checkout_entry(struct cache_entry *ce, struct checkout *state, char *topath)
 {
-       static char path[MAXPATHLEN+1];
+       static char path[PATH_MAX + 1];
        struct stat st;
        int len = state->base_dir_len;
 
@@ -172,5 +172,3 @@ int checkout_entry(struct cache_entry *ce, struct checkout *state, char *topath)
        create_directories(path, state);
        return write_entry(ce, path, state, 0);
 }
-
-
index e6bd0033b4666f52dc756b6e2b0d5a1745b0c6b9..5fae9ac3056dd00beba3b9a13be99f7bb39d584e 100644 (file)
@@ -25,8 +25,9 @@ int zlib_compression_level = Z_DEFAULT_COMPRESSION;
 int pager_in_use;
 int pager_use_color = 1;
 
-static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
-       *git_graft_file;
+static const char *git_dir;
+static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
+
 static void setup_git_env(void)
 {
        git_dir = getenv(GIT_DIR_ENVIRONMENT);
@@ -49,7 +50,7 @@ static void setup_git_env(void)
                git_graft_file = strdup(git_path("info/grafts"));
 }
 
-char *get_git_dir(void)
+const char *get_git_dir(void)
 {
        if (!git_dir)
                setup_git_env();
index e18c1489a1ab8620cade351ec502828b10a41ac4..377feded1ccafdece86499d1917d297145fd28ac 100644 (file)
@@ -404,7 +404,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
                        continue;
                }
 
-               memcpy(ref->new_sha1, local, 20);
+               hashcpy(ref->new_sha1, local);
                if (!verbose)
                        continue;
                fprintf(stderr,
diff --git a/fetch.c b/fetch.c
index aeb6bf2639cc75b6f738348bcc267179a8a0da65..ef60b045eaa0a55ba65499187a3aac082ffb6af2 100644 (file)
--- a/fetch.c
+++ b/fetch.c
@@ -84,7 +84,7 @@ static int process_commit(struct commit *commit)
        if (commit->object.flags & COMPLETE)
                return 0;
 
-       memcpy(current_commit_sha1, commit->object.sha1, 20);
+       hashcpy(current_commit_sha1, commit->object.sha1);
 
        pull_say("walk %s\n", sha1_to_hex(commit->object.sha1));
 
index 31e00d84b30f95c713b3dc6a654b4ef8459c6729..ae0ec8d039cfce698daa8a9f44c7f49b932373c8 100644 (file)
@@ -356,7 +356,7 @@ static void add_sha1_list(unsigned char *sha1, unsigned long ino)
        int nr;
 
        entry->ino = ino;
-       memcpy(entry->sha1, sha1, 20);
+       hashcpy(entry->sha1, sha1);
        nr = sha1_list.nr;
        if (nr == MAX_SHA1_ENTRIES) {
                fsck_sha1_list();
index f0e8831fa49ae46eb7ad664b6ad489e3974c9f91..8832573fee9d3b8d4be92786ae5116ee6e5405bb 100755 (executable)
@@ -51,9 +51,6 @@ patch=$tmp-patch
 mkdir $patch
 trap "rm -rf $tmp-*" 0 1 2 3 15
 
-_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"
-
 for c in $inup
 do
        git-diff-tree -p $c
index b2e18954c03ff502053cb74d142faab7d2a8dacb..91f2b0d3f0cf9d8539e7e09adc057dc337caae21 100644 (file)
@@ -172,7 +172,4 @@ static inline int sane_case(int x, int high)
        return x;
 }
 
-#ifndef MAXPATHLEN
-#define MAXPATHLEN 256
-#endif
 #endif
index 36fc8ce25b39682ba256a8d39bf9a393907ef43d..3133b5bd25ca7ad3c2a5451ee9c2e0f4514cd980 100755 (executable)
@@ -3,9 +3,6 @@
 USAGE='[--mixed | --soft | --hard]  [<commit-ish>]'
 . git-sh-setup
 
-tmp=${GIT_DIR}/reset.$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
-
 update=
 reset_type=--mixed
 case "$1" in
index a83c7e90948fc3fe1b1ac82335704d66d060edab..746c525079317491e35827f331922e17e5fbd089 100755 (executable)
@@ -510,7 +510,7 @@ sub send_message
                                        if ($2 eq $from) {
                                                next if ($suppress_from);
                                        }
-                                       else {
+                                       elsif ($1 eq 'From') {
                                                $author_not_sender = $2;
                                        }
                                        printf("(mbox) Adding cc: %s from line '%s'\n",
index 0d58bb9b37944728baa7d8af17d714f6ee8b4509..0290850b6639b4865d0941089d00a8c2ac5de366 100755 (executable)
@@ -51,7 +51,8 @@
        $_message, $_file, $_follow_parent, $_no_metadata,
        $_template, $_shared, $_no_default_regex, $_no_graft_copy,
        $_limit, $_verbose, $_incremental, $_oneline, $_l_fmt, $_show_commit,
-       $_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m);
+       $_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m,
+       $_merge, $_strategy, $_dry_run);
 my (@_branch_from, %tree_map, %users, %rusers, %equiv);
 my ($_svn_co_url_revs, $_svn_pg_peg_revs);
 my @repo_path_split_cache;
                        { 'message|m=s' => \$_message,
                          'file|F=s' => \$_file,
                        %cmt_opts } ],
+       dcommit => [ \&dcommit, 'Commit several diffs to merge with upstream',
+                       { 'merge|m|M' => \$_merge,
+                         'strategy|s=s' => \$_strategy,
+                         'dry-run|n' => \$_dry_run,
+                       %cmt_opts } ],
 );
 
 my $cmd;
@@ -500,6 +506,8 @@ sub commit_lib {
        my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
        my $commit_msg = "$GIT_SVN_DIR/.svn-commit.tmp.$$";
 
+       my $repo;
+       ($repo, $SVN_PATH) = repo_path_split($SVN_URL);
        set_svn_commit_env();
        foreach my $c (@revs) {
                my $log_msg = get_commit_message($c, $commit_msg);
@@ -508,6 +516,8 @@ sub commit_lib {
                # can't track down... (it's probably in the SVN code)
                defined(my $pid = open my $fh, '-|') or croak $!;
                if (!$pid) {
+                       $SVN_LOG = libsvn_connect($repo);
+                       $SVN = libsvn_connect($repo);
                        my $ed = SVN::Git::Editor->new(
                                        {       r => $r_last,
                                                ra => $SVN,
@@ -557,6 +567,33 @@ sub commit_lib {
        unlink $commit_msg;
 }
 
+sub dcommit {
+       my $gs = "refs/remotes/$GIT_SVN";
+       chomp(my @refs = safe_qx(qw/git-rev-list --no-merges/, "$gs..HEAD"));
+       foreach my $d (reverse @refs) {
+               if ($_dry_run) {
+                       print "diff-tree $d~1 $d\n";
+               } else {
+                       commit_diff("$d~1", $d);
+               }
+       }
+       return if $_dry_run;
+       fetch();
+       my @diff = safe_qx(qw/git-diff-tree HEAD/, $gs);
+       my @finish;
+       if (@diff) {
+               @finish = qw/rebase/;
+               push @finish, qw/--merge/ if $_merge;
+               push @finish, "--strategy=$_strategy" if $_strategy;
+               print STDERR "W: HEAD and $gs differ, using @finish:\n", @diff;
+       } else {
+               print "No changes between current HEAD and $gs\n",
+                     "Hard resetting to the latest $gs\n";
+               @finish = qw/reset --hard/;
+       }
+       sys('git', @finish, $gs);
+}
+
 sub show_ignore {
        $SVN_URL ||= file_to_s("$GIT_SVN_DIR/info/url");
        $_use_lib ? show_ignore_lib() : show_ignore_cmd();
@@ -782,6 +819,7 @@ sub commit_diff {
        } else {
                $ed->close_edit;
        }
+       $_message = $_file = undef;
 }
 
 ########################### utility functions #########################
diff --git a/git.c b/git.c
index 930998bbe542cbaa92b3f16a6b0dc0d6ad43b874..bd07289d71a75ad0280bae21c64c4c4be86f80d2 100644 (file)
--- a/git.c
+++ b/git.c
@@ -120,7 +120,7 @@ static int split_cmdline(char *cmdline, const char ***argv)
                                ; /* skip */
                        if (count >= size) {
                                size += 16;
-                               *argv = realloc(*argv, sizeof(char*) * size);
+                               *argv = xrealloc(*argv, sizeof(char*) * size);
                        }
                        (*argv)[count++] = cmdline + dst;
                } else if(!quoted && (c == '\'' || c == '"')) {
@@ -191,8 +191,8 @@ static int handle_alias(int *argcp, const char ***argv)
                        fflush(stderr);
                }
 
-               new_argv = realloc(new_argv, sizeof(char*) *
-                                  (count + *argcp + 1));
+               new_argv = xrealloc(new_argv, sizeof(char*) *
+                                   (count + *argcp + 1));
                /* insert after command name */
                memcpy(new_argv + count, *argv + 1, sizeof(char*) * *argcp);
                new_argv[count+*argcp] = NULL;
@@ -263,6 +263,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                { "stripspace", cmd_stripspace },
                { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
                { "tar-tree", cmd_tar_tree, RUN_SETUP },
+               { "zip-tree", cmd_zip_tree, RUN_SETUP },
                { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
                { "update-index", cmd_update_index, RUN_SETUP },
                { "update-ref", cmd_update_ref, RUN_SETUP },
@@ -292,11 +293,11 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                if (p->option & USE_PAGER)
                        setup_pager();
                if (getenv("GIT_TRACE")) {
-                       int i;
+                       int j;
                        fprintf(stderr, "trace: built-in: git");
-                       for (i = 0; i < argc; ++i) {
+                       for (j = 0; j < argc; ++j) {
                                fputc(' ', stderr);
-                               sq_quote_print(stderr, argv[i]);
+                               sq_quote_print(stderr, argv[j]);
                        }
                        putc('\n', stderr);
                        fflush(stderr);
index 7c92ac30ce2fcabc46455d7f7b1dc44829705335..966c54a63cacf20d2a71241f738df0378e46f569 100755 (executable)
@@ -996,10 +996,11 @@ sub git_header_html {
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
-<!-- git web interface v$version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
+<!-- git web interface version $version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
 <!-- git core binaries version $git_version -->
 <head>
 <meta http-equiv="content-type" content="$content_type; charset=utf-8"/>
+<meta name="generator" content="gitweb/$version git/$git_version"/>
 <meta name="robots" content="index, nofollow"/>
 <title>$title</title>
 <link rel="stylesheet" type="text/css" href="$stylesheet"/>
@@ -1881,7 +1882,7 @@ sub git_blame {
                chomp $line;
                $line_class_num = ($line_class_num + 1) % $line_class_len;
 
-               if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) \+\d\d\d\d\t(\d+)\)(.*)$/) {
+               if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) [+-]\d\d\d\d\t(\d+)\)(.*)$/) {
                        $long_rev = $1;
                        $author   = $2;
                        $time     = $3;
index 7f07d2a967fdecb497344817700962e9e213d3dd..7619b338feb92a431268fc5a3963415af1b53e99 100644 (file)
@@ -301,7 +301,7 @@ static void finish_object_request(struct object_request *obj_req)
                unlink(obj_req->tmpfile);
                return;
        }
-       if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) {
+       if (hashcmp(obj_req->sha1, obj_req->real_sha1)) {
                unlink(obj_req->tmpfile);
                return;
        }
@@ -393,7 +393,7 @@ void prefetch(unsigned char *sha1)
        char *filename = sha1_file_name(sha1);
 
        newreq = xmalloc(sizeof(*newreq));
-       memcpy(newreq->sha1, sha1, 20);
+       hashcpy(newreq->sha1, sha1);
        newreq->repo = alt;
        newreq->url = NULL;
        newreq->local = -1;
@@ -1070,7 +1070,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
        int ret = 0;
        struct object_request *obj_req = object_queue_head;
 
-       while (obj_req != NULL && memcmp(obj_req->sha1, sha1, 20))
+       while (obj_req != NULL && hashcmp(obj_req->sha1, sha1))
                obj_req = obj_req->next;
        if (obj_req == NULL)
                return error("Couldn't find request for %s in the queue", hex);
@@ -1109,7 +1109,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
        } else if (obj_req->zret != Z_STREAM_END) {
                corrupt_object_found++;
                ret = error("File %s (%s) corrupt", hex, obj_req->url);
-       } else if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) {
+       } else if (hashcmp(obj_req->sha1, obj_req->real_sha1)) {
                ret = error("File %s has bad hash", hex);
        } else if (obj_req->rename < 0) {
                ret = error("unable to write sha1 filename %s",
index 2bd984576523a7f2b646095eae92d08e7476b023..04cb238e965efdff564a9b57ce1253b274268c46 100644 (file)
@@ -745,7 +745,7 @@ static void finish_request(struct transfer_request *request)
                        SHA1_Final(request->real_sha1, &request->c);
                        if (request->zret != Z_STREAM_END) {
                                unlink(request->tmpfile);
-                       } else if (memcmp(request->obj->sha1, request->real_sha1, 20)) {
+                       } else if (hashcmp(request->obj->sha1, request->real_sha1)) {
                                unlink(request->tmpfile);
                        } else {
                                request->rename =
@@ -1700,7 +1700,7 @@ static int locking_available(void)
        return lock_flags;
 }
 
-struct object_list **add_one_object(struct object *obj, struct object_list **p)
+static struct object_list **add_one_object(struct object *obj, struct object_list **p)
 {
        struct object_list *entry = xmalloc(sizeof(struct object_list));
        entry->item = obj;
@@ -1874,7 +1874,7 @@ static int one_local_ref(const char *refname, const unsigned char *sha1)
        struct ref *ref;
        int len = strlen(refname) + 1;
        ref = xcalloc(1, sizeof(*ref) + len);
-       memcpy(ref->new_sha1, sha1, 20);
+       hashcpy(ref->new_sha1, sha1);
        memcpy(ref->name, refname, len);
        *local_tail = ref;
        local_tail = &ref->next;
@@ -1909,7 +1909,7 @@ static void one_remote_ref(char *refname)
        }
 
        ref = xcalloc(1, sizeof(*ref) + len);
-       memcpy(ref->old_sha1, remote_sha1, 20);
+       hashcpy(ref->old_sha1, remote_sha1);
        memcpy(ref->name, refname, len);
        *remote_tail = ref;
        remote_tail = &ref->next;
@@ -2164,7 +2164,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
        if (*symref != NULL)
                free(*symref);
        *symref = NULL;
-       memset(sha1, 0, 20);
+       hashclr(sha1);
 
        if (buffer.posn == 0)
                return;
@@ -2416,7 +2416,7 @@ int main(int argc, char **argv)
 
                if (!ref->peer_ref)
                        continue;
-               if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
+               if (!hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {
                        if (push_verbosely || 1)
                                fprintf(stderr, "'%s': up-to-date\n", ref->name);
                        continue;
@@ -2445,7 +2445,7 @@ int main(int argc, char **argv)
                                continue;
                        }
                }
-               memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
+               hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
                if (is_zero_sha1(ref->new_sha1)) {
                        error("cannot happen anymore");
                        rc = -3;
index b20659c2591f2669e03570c9809249b37ec58c38..80bc6cb45b1a91c31dbdf18b48399b7a7a6b2737 100644 (file)
@@ -82,7 +82,7 @@ static void parse_pack_header(void)
        SHA1_Init(&ctx);
        SHA1_Update(&ctx, pack_base, pack_size - 20);
        SHA1_Final(sha1, &ctx);
-       if (memcmp(sha1, pack_base + pack_size - 20, 20))
+       if (hashcmp(sha1, pack_base + pack_size - 20))
                die("packfile '%s' SHA1 mismatch", pack_name);
 }
 
@@ -161,7 +161,7 @@ static void *unpack_raw_entry(unsigned long offset,
        case OBJ_DELTA:
                if (pos + 20 >= pack_limit)
                        bad_object(offset, "object extends past end of pack");
-               memcpy(delta_base, pack_base + pos, 20);
+               hashcpy(delta_base, pack_base + pos);
                pos += 20;
                /* fallthru */
        case OBJ_COMMIT:
@@ -189,7 +189,7 @@ static int find_delta(const unsigned char *base_sha1)
                 struct delta_entry *delta = &deltas[next];
                 int cmp;
 
-                cmp = memcmp(base_sha1, delta->base_sha1, 20);
+                cmp = hashcmp(base_sha1, delta->base_sha1);
                 if (!cmp)
                         return next;
                 if (cmp < 0) {
@@ -210,9 +210,9 @@ static int find_deltas_based_on_sha1(const unsigned char *base_sha1,
 
        if (first < 0)
                return -1;
-       while (first > 0 && !memcmp(deltas[first-1].base_sha1, base_sha1, 20))
+       while (first > 0 && !hashcmp(deltas[first - 1].base_sha1, base_sha1))
                --first;
-       while (last < end && !memcmp(deltas[last+1].base_sha1, base_sha1, 20))
+       while (last < end && !hashcmp(deltas[last + 1].base_sha1, base_sha1))
                ++last;
        *first_index = first;
        *last_index = last;
@@ -278,7 +278,7 @@ static int compare_delta_entry(const void *a, const void *b)
 {
        const struct delta_entry *delta_a = a;
        const struct delta_entry *delta_b = b;
-       return memcmp(delta_a->base_sha1, delta_b->base_sha1, 20);
+       return hashcmp(delta_a->base_sha1, delta_b->base_sha1);
 }
 
 static void parse_pack_objects(void)
@@ -304,7 +304,7 @@ static void parse_pack_objects(void)
                if (obj->type == OBJ_DELTA) {
                        struct delta_entry *delta = &deltas[nr_deltas++];
                        delta->obj = obj;
-                       memcpy(delta->base_sha1, base_sha1, 20);
+                       hashcpy(delta->base_sha1, base_sha1);
                } else
                        sha1_object(data, data_size, obj->type, obj->sha1);
                free(data);
@@ -350,7 +350,7 @@ static int sha1_compare(const void *_a, const void *_b)
 {
        struct object_entry *a = *(struct object_entry **)_a;
        struct object_entry *b = *(struct object_entry **)_b;
-       return memcmp(a->sha1, b->sha1, 20);
+       return hashcmp(a->sha1, b->sha1);
 }
 
 static void write_index_file(const char *index_name, unsigned char *sha1)
index 7cf00be6d51b17ca60979a9c856e67405906d9a7..c2e9a867edb5b843150cd3df47583f49f15314cb 100644 (file)
@@ -152,7 +152,7 @@ static int same_entry(struct name_entry *a, struct name_entry *b)
 {
        return  a->sha1 &&
                b->sha1 &&
-               !memcmp(a->sha1, b->sha1, 20) &&
+               !hashcmp(a->sha1, b->sha1) &&
                a->mode == b->mode;
 }
 
index 93241385e4aee76fc42db5849365740c474b9bdd..56205d1e0053cdcb7236bde199817a5529d3f433 100644 (file)
--- a/mktree.c
+++ b/mktree.c
@@ -30,7 +30,7 @@ static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
        ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
        ent->mode = mode;
        ent->len = len;
-       memcpy(ent->sha1, sha1, 20);
+       hashcpy(ent->sha1, sha1);
        memcpy(ent->name, path, len+1);
 }
 
@@ -64,7 +64,7 @@ static void write_tree(unsigned char *sha1)
                offset += sprintf(buffer + offset, "%o ", ent->mode);
                offset += sprintf(buffer + offset, "%s", ent->name);
                buffer[offset++] = 0;
-               memcpy(buffer + offset, ent->sha1, 20);
+               hashcpy((unsigned char*)buffer + offset, ent->sha1);
                offset += 20;
        }
        write_sha1_file(buffer, offset, tree_type, sha1);
index b5d8ed467d1c10c2f2dd596717159f7ee48a8007..60bf16b902033d9f256282201ca7aeca74855d7e 100644 (file)
--- a/object.c
+++ b/object.c
@@ -58,7 +58,7 @@ struct object *lookup_object(const unsigned char *sha1)
 
        i = hashtable_index(sha1);
        while ((obj = obj_hash[i]) != NULL) {
-               if (!memcmp(sha1, obj->sha1, 20))
+               if (!hashcmp(sha1, obj->sha1))
                        break;
                i++;
                if (i == obj_hash_size)
@@ -91,7 +91,7 @@ void created_object(const unsigned char *sha1, struct object *obj)
        obj->used = 0;
        obj->type = OBJ_NONE;
        obj->flags = 0;
-       memcpy(obj->sha1, sha1, 20);
+       hashcpy(obj->sha1, sha1);
 
        if (obj_hash_size - 1 <= nr_objs * 2)
                grow_object_hash();
index 3a62e1b7e40927390e10ae63943596a367ecbf47..04c6c0082119360e307130f10972371236905747 100644 (file)
@@ -29,10 +29,10 @@ static int verify_packfile(struct packed_git *p)
        pack_base = p->pack_base;
        SHA1_Update(&ctx, pack_base, pack_size - 20);
        SHA1_Final(sha1, &ctx);
-       if (memcmp(sha1, (char *) pack_base + pack_size - 20, 20))
+       if (hashcmp(sha1, (unsigned char *)pack_base + pack_size - 20))
                return error("Packfile %s SHA1 mismatch with itself",
                             p->pack_name);
-       if (memcmp(sha1, (char *) index_base + index_size - 40, 20))
+       if (hashcmp(sha1, (unsigned char *)index_base + index_size - 40))
                return error("Packfile %s SHA1 mismatch with idx",
                             p->pack_name);
 
@@ -135,7 +135,7 @@ int verify_pack(struct packed_git *p, int verbose)
        SHA1_Init(&ctx);
        SHA1_Update(&ctx, index_base, index_size - 20);
        SHA1_Final(sha1, &ctx);
-       if (memcmp(sha1, (char *) index_base + index_size - 20, 20))
+       if (hashcmp(sha1, (unsigned char *)index_base + index_size - 20))
                ret = error("Packfile index for %s SHA1 mismatch",
                            p->pack_name);
 
index 92a09ed36281b293a8c9002a33ab80f740949a37..edb5524fc48b49bca5c0dd319caf348c9bda7c23 100644 (file)
@@ -139,7 +139,7 @@ static inline struct llist_item *llist_insert_sorted_unique(struct llist *list,
 
        l = (hint == NULL) ? list->front : hint;
        while (l) {
-               int cmp = memcmp(l->sha1, sha1, 20);
+               int cmp = hashcmp(l->sha1, sha1);
                if (cmp > 0) { /* we insert before this entry */
                        return llist_insert(list, prev, sha1);
                }
@@ -162,7 +162,7 @@ static inline struct llist_item * llist_sorted_remove(struct llist *list, const
        l = (hint == NULL) ? list->front : hint;
        prev = NULL;
        while (l) {
-               int cmp = memcmp(l->sha1, sha1, 20);
+               int cmp = hashcmp(l->sha1, sha1);
                if (cmp > 0) /* not in list, since sorted */
                        return prev;
                if(!cmp) { /* found */
@@ -256,7 +256,7 @@ static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
        while (p1_off <= p1->pack->index_size - 3 * 20 &&
               p2_off <= p2->pack->index_size - 3 * 20)
        {
-               int cmp = memcmp(p1_base + p1_off, p2_base + p2_off, 20);
+               int cmp = hashcmp(p1_base + p1_off, p2_base + p2_off);
                /* cmp ~ p1 - p2 */
                if (cmp == 0) {
                        p1_hint = llist_sorted_remove(p1->unique_objects,
@@ -351,16 +351,16 @@ static size_t sizeof_union(struct packed_git *p1, struct packed_git *p2)
 {
        size_t ret = 0;
        int p1_off, p2_off;
-       char *p1_base, *p2_base;
+       unsigned char *p1_base, *p2_base;
 
        p1_off = p2_off = 256 * 4 + 4;
-       p1_base = (char *)p1->index_base;
-       p2_base = (char *)p2->index_base;
+       p1_base = (unsigned char *)p1->index_base;
+       p2_base = (unsigned char *)p2->index_base;
 
        while (p1_off <= p1->index_size - 3 * 20 &&
               p2_off <= p2->index_size - 3 * 20)
        {
-               int cmp = memcmp(p1_base + p1_off, p2_base + p2_off, 20);
+               int cmp = hashcmp(p1_base + p1_off, p2_base + p2_off);
                /* cmp ~ p1 - p2 */
                if (cmp == 0) {
                        ret++;
index 3b4c80f764bd11a740a7cce60f2e8c062706e897..086d2d9c68835c6a7434932f6e3b430e0906578d 100644 (file)
@@ -47,7 +47,7 @@ static void generate_id_list(void)
 
                if (!get_sha1_hex(p, n)) {
                        flush_current_id(patchlen, sha1, &ctx);
-                       memcpy(sha1, n, 20);
+                       hashcpy(sha1, n);
                        patchlen = 0;
                        continue;
                }
index 6bec833eecae934af1dce18683c70522481b002a..b6982eac416fe765e1a570cdb25298e83264c81e 100644 (file)
@@ -60,7 +60,7 @@ static int ce_compare_data(struct cache_entry *ce, struct stat *st)
        if (fd >= 0) {
                unsigned char sha1[20];
                if (!index_fd(sha1, fd, st, 0, NULL))
-                       match = memcmp(sha1, ce->sha1, 20);
+                       match = hashcmp(sha1, ce->sha1);
                /* index_fd() closed the file descriptor already */
        }
        return match;
@@ -744,7 +744,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
        SHA1_Init(&c);
        SHA1_Update(&c, hdr, size - 20);
        SHA1_Final(sha1, &c);
-       if (memcmp(sha1, (char *) hdr + size - 20, 20))
+       if (hashcmp(sha1, (unsigned char *)hdr + size - 20))
                return error("bad index file sha1 signature");
        return 0;
 }
index 81e91909b8ac88423c550a6489285b003378c5f0..201531626c2a60dffd1720ab4d00d7023bcbc78e 100644 (file)
@@ -247,8 +247,8 @@ static void read_head_info(void)
                                report_status = 1;
                }
                cmd = xmalloc(sizeof(struct command) + len - 80);
-               memcpy(cmd->old_sha1, old_sha1, 20);
-               memcpy(cmd->new_sha1, new_sha1, 20);
+               hashcpy(cmd->old_sha1, old_sha1);
+               hashcpy(cmd->new_sha1, new_sha1);
                memcpy(cmd->ref_name, line + 82, len - 81);
                cmd->error_string = "n/a (unpacker error)";
                cmd->next = NULL;
diff --git a/refs.c b/refs.c
index 86ef91661400376f6bdc2af37fac7982f8872df9..e70ef0ae0fe58671a35b71a55fbf81425ee84581 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -29,7 +29,7 @@ const char *resolve_ref(const char *path, unsigned char *sha1, int reading)
                if (lstat(path, &st) < 0) {
                        if (reading || errno != ENOENT)
                                return NULL;
-                       memset(sha1, 0, 20);
+                       hashclr(sha1);
                        return path;
                }
 
@@ -281,7 +281,7 @@ static struct ref_lock *verify_lock(struct ref_lock *lock,
                unlock_ref(lock);
                return NULL;
        }
-       if (memcmp(lock->old_sha1, old_sha1, 20)) {
+       if (hashcmp(lock->old_sha1, old_sha1)) {
                error("Ref %s is at %s but expected %s", lock->ref_file,
                        sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1));
                unlock_ref(lock);
@@ -411,7 +411,7 @@ int write_ref_sha1(struct ref_lock *lock,
 
        if (!lock)
                return -1;
-       if (!lock->force_write && !memcmp(lock->old_sha1, sha1, 20)) {
+       if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
                unlock_ref(lock);
                return 0;
        }
@@ -475,7 +475,7 @@ int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1)
                                        die("Log %s is corrupt.", logfile);
                                if (get_sha1_hex(rec + 41, sha1))
                                        die("Log %s is corrupt.", logfile);
-                               if (memcmp(logged_sha1, sha1, 20)) {
+                               if (hashcmp(logged_sha1, sha1)) {
                                        tz = strtoul(tz_c, NULL, 10);
                                        fprintf(stderr,
                                                "warning: Log %s has gap after %s.\n",
@@ -489,7 +489,7 @@ int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1)
                        else {
                                if (get_sha1_hex(rec + 41, logged_sha1))
                                        die("Log %s is corrupt.", logfile);
-                               if (memcmp(logged_sha1, sha1, 20)) {
+                               if (hashcmp(logged_sha1, sha1)) {
                                        tz = strtoul(tz_c, NULL, 10);
                                        fprintf(stderr,
                                                "warning: Log %s unexpectedly ended on %s.\n",
index 5a91d06b980d710e30a80c353a636ca1ca6b9a55..1d89d72738ff917d29373d50c2c2cc9bbd10b2c0 100644 (file)
@@ -496,7 +496,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
                it = get_reference(revs, arg, sha1, 0);
                if (it->type != OBJ_TAG)
                        break;
-               memcpy(sha1, ((struct tag*)it)->tagged->sha1, 20);
+               hashcpy(sha1, ((struct tag*)it)->tagged->sha1);
        }
        if (it->type != OBJ_COMMIT)
                return 0;
index 43e10b0a620cc3d51d8905a9de36350ca6b67966..fd79a61923ddc20af216ccd252e40bf38a70eccb 100644 (file)
@@ -185,7 +185,7 @@ static int one_local_ref(const char *refname, const unsigned char *sha1)
        struct ref *ref;
        int len = strlen(refname) + 1;
        ref = xcalloc(1, sizeof(*ref) + len);
-       memcpy(ref->new_sha1, sha1, 20);
+       hashcpy(ref->new_sha1, sha1);
        memcpy(ref->name, refname, len);
        *local_tail = ref;
        local_tail = &ref->next;
@@ -265,7 +265,7 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
                char old_hex[60], *new_hex;
                if (!ref->peer_ref)
                        continue;
-               if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
+               if (!hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {
                        if (verbose)
                                fprintf(stderr, "'%s': up-to-date\n", ref->name);
                        continue;
@@ -310,7 +310,7 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
                                continue;
                        }
                }
-               memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
+               hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
                if (is_zero_sha1(ref->new_sha1)) {
                        error("cannot happen anymore");
                        ret = -3;
index 18dece46b1e248a4e52e9ead3bf172ed6ab78236..46272b591645e444396ae683673620594f336a7c 100644 (file)
@@ -463,6 +463,7 @@ int use_packed_git(struct packed_git *p)
                int fd;
                struct stat st;
                void *map;
+               struct pack_header *hdr;
 
                pack_mapped += p->pack_size;
                while (PACK_MAX_SZ < pack_mapped && unuse_one_packed_git())
@@ -482,13 +483,24 @@ int use_packed_git(struct packed_git *p)
                        die("packfile %s cannot be mapped.", p->pack_name);
                p->pack_base = map;
 
+               /* Check if we understand this pack file.  If we don't we're
+                * likely too old to handle it.
+                */
+               hdr = map;
+               if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
+                       die("packfile %s isn't actually a pack.", p->pack_name);
+               if (!pack_version_ok(hdr->hdr_version))
+                       die("packfile %s is version %i and not supported"
+                               " (try upgrading GIT to a newer version)",
+                               p->pack_name, ntohl(hdr->hdr_version));
+
                /* Check if the pack file matches with the index file.
                 * this is cheap.
                 */
-               if (memcmp((char*)(p->index_base) + p->index_size - 40,
-                          (char *) p->pack_base + p->pack_size - 20,
-                          20)) {
-
+               if (hashcmp((unsigned char *)(p->index_base) +
+                           p->index_size - 40,
+                           (unsigned char *)p->pack_base +
+                           p->pack_size - 20)) {
                        die("packfile %s does not match index.", p->pack_name);
                }
        }
@@ -528,7 +540,7 @@ struct packed_git *add_packed_git(char *path, int path_len, int local)
        p->pack_use_cnt = 0;
        p->pack_local = local;
        if ((path_len > 44) && !get_sha1_hex(path + path_len - 44, sha1))
-               memcpy(p->sha1, sha1, 20);
+               hashcpy(p->sha1, sha1);
        return p;
 }
 
@@ -559,7 +571,7 @@ struct packed_git *parse_pack_index_file(const unsigned char *sha1, char *idx_pa
        p->pack_base = NULL;
        p->pack_last_used = 0;
        p->pack_use_cnt = 0;
-       memcpy(p->sha1, sha1, 20);
+       hashcpy(p->sha1, sha1);
        return p;
 }
 
@@ -643,7 +655,7 @@ int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long siz
        SHA1_Update(&c, header, 1+sprintf(header, "%s %lu", type, size));
        SHA1_Update(&c, map, size);
        SHA1_Final(real_sha1, &c);
-       return memcmp(sha1, real_sha1, 20) ? -1 : 0;
+       return hashcmp(sha1, real_sha1) ? -1 : 0;
 }
 
 void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
@@ -905,23 +917,19 @@ static unsigned long unpack_object_header(struct packed_git *p, unsigned long of
        enum object_type *type, unsigned long *sizep)
 {
        unsigned shift;
-       unsigned char *pack, c;
+       unsigned char c;
        unsigned long size;
 
        if (offset >= p->pack_size)
                die("object offset outside of pack file");
-
-       pack =  (unsigned char *) p->pack_base + offset;
-       c = *pack++;
-       offset++;
+       c = *((unsigned char *)p->pack_base + offset++);
        *type = (c >> 4) & 7;
        size = c & 15;
        shift = 4;
        while (c & 0x80) {
                if (offset >= p->pack_size)
                        die("object offset outside of pack file");
-               c = *pack++;
-               offset++;
+               c = *((unsigned char *)p->pack_base + offset++);
                size += (c & 0x7f) << shift;
                shift += 7;
        }
@@ -941,7 +949,7 @@ int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,
        ptr = unpack_object_header(p, ptr, kindp, sizep);
        if (*kindp != OBJ_DELTA)
                goto done;
-       memcpy(base, (char *) p->pack_base + ptr, 20);
+       hashcpy(base, (unsigned char *) p->pack_base + ptr);
        status = 0;
  done:
        unuse_packed_git(p);
@@ -969,7 +977,7 @@ void packed_object_info_detail(struct pack_entry *e,
                if (p->pack_size <= offset + 20)
                        die("pack file %s records an incomplete delta base",
                            p->pack_name);
-               memcpy(base_sha1, pack, 20);
+               hashcpy(base_sha1, pack);
                do {
                        struct pack_entry base_ent;
                        unsigned long junk;
@@ -984,16 +992,10 @@ void packed_object_info_detail(struct pack_entry *e,
        }
        switch (kind) {
        case OBJ_COMMIT:
-               strcpy(type, commit_type);
-               break;
        case OBJ_TREE:
-               strcpy(type, tree_type);
-               break;
        case OBJ_BLOB:
-               strcpy(type, blob_type);
-               break;
        case OBJ_TAG:
-               strcpy(type, tag_type);
+               strcpy(type, type_names[kind]);
                break;
        default:
                die("corrupted pack file %s containing object of kind %d",
@@ -1024,16 +1026,10 @@ static int packed_object_info(struct pack_entry *entry,
                unuse_packed_git(p);
                return retval;
        case OBJ_COMMIT:
-               strcpy(type, commit_type);
-               break;
        case OBJ_TREE:
-               strcpy(type, tree_type);
-               break;
        case OBJ_BLOB:
-               strcpy(type, blob_type);
-               break;
        case OBJ_TAG:
-               strcpy(type, tag_type);
+               strcpy(type, type_names[kind]);
                break;
        default:
                die("corrupted pack file %s containing object of kind %d",
@@ -1045,26 +1041,49 @@ static int packed_object_info(struct pack_entry *entry,
        return 0;
 }
 
-/* forward declaration for a mutually recursive function */
-static void *unpack_entry(struct pack_entry *, char *, unsigned long *);
+static void *unpack_compressed_entry(struct packed_git *p,
+                                   unsigned long offset,
+                                   unsigned long size)
+{
+       int st;
+       z_stream stream;
+       unsigned char *buffer;
+
+       buffer = xmalloc(size + 1);
+       buffer[size] = 0;
+       memset(&stream, 0, sizeof(stream));
+       stream.next_in = (unsigned char*)p->pack_base + offset;
+       stream.avail_in = p->pack_size - offset;
+       stream.next_out = buffer;
+       stream.avail_out = size;
+
+       inflateInit(&stream);
+       st = inflate(&stream, Z_FINISH);
+       inflateEnd(&stream);
+       if ((st != Z_STREAM_END) || stream.total_out != size) {
+               free(buffer);
+               return NULL;
+       }
 
-static void *unpack_delta_entry(unsigned char *base_sha1,
+       return buffer;
+}
+
+static void *unpack_delta_entry(struct packed_git *p,
+                               unsigned long offset,
                                unsigned long delta_size,
-                               unsigned long left,
                                char *type,
-                               unsigned long *sizep,
-                               struct packed_git *p)
+                               unsigned long *sizep)
 {
        struct pack_entry base_ent;
-       void *data, *delta_data, *result, *base;
-       unsigned long data_size, result_size, base_size;
-       z_stream stream;
-       int st;
+       void *delta_data, *result, *base;
+       unsigned long result_size, base_size;
+       unsigned char* base_sha1;
 
-       if (left < 20)
+       if ((offset + 20) >= p->pack_size)
                die("truncated pack file");
 
        /* The base entry _must_ be in the same pack */
+       base_sha1 = (unsigned char*)p->pack_base + offset;
        if (!find_pack_entry_one(base_sha1, &base_ent, p))
                die("failed to find delta-pack base object %s",
                    sha1_to_hex(base_sha1));
@@ -1073,23 +1092,7 @@ static void *unpack_delta_entry(unsigned char *base_sha1,
                die("failed to read delta-pack base object %s",
                    sha1_to_hex(base_sha1));
 
-       data = base_sha1 + 20;
-       data_size = left - 20;
-       delta_data = xmalloc(delta_size);
-
-       memset(&stream, 0, sizeof(stream));
-
-       stream.next_in = data;
-       stream.avail_in = data_size;
-       stream.next_out = delta_data;
-       stream.avail_out = delta_size;
-
-       inflateInit(&stream);
-       st = inflate(&stream, Z_FINISH);
-       inflateEnd(&stream);
-       if ((st != Z_STREAM_END) || stream.total_out != delta_size)
-               die("delta data unpack failed");
-
+       delta_data = unpack_compressed_entry(p, offset + 20, delta_size);
        result = patch_delta(base, base_size,
                             delta_data, delta_size,
                             &result_size);
@@ -1101,33 +1104,6 @@ static void *unpack_delta_entry(unsigned char *base_sha1,
        return result;
 }
 
-static void *unpack_non_delta_entry(unsigned char *data,
-                                   unsigned long size,
-                                   unsigned long left)
-{
-       int st;
-       z_stream stream;
-       unsigned char *buffer;
-
-       buffer = xmalloc(size + 1);
-       buffer[size] = 0;
-       memset(&stream, 0, sizeof(stream));
-       stream.next_in = data;
-       stream.avail_in = left;
-       stream.next_out = buffer;
-       stream.avail_out = size;
-
-       inflateInit(&stream);
-       st = inflate(&stream, Z_FINISH);
-       inflateEnd(&stream);
-       if ((st != Z_STREAM_END) || stream.total_out != size) {
-               free(buffer);
-               return NULL;
-       }
-
-       return buffer;
-}
-
 static void *unpack_entry(struct pack_entry *entry,
                          char *type, unsigned long *sizep)
 {
@@ -1148,36 +1124,23 @@ void *unpack_entry_gently(struct pack_entry *entry,
                          char *type, unsigned long *sizep)
 {
        struct packed_git *p = entry->p;
-       unsigned long offset, size, left;
-       unsigned char *pack;
+       unsigned long offset, size;
        enum object_type kind;
-       void *retval;
 
        offset = unpack_object_header(p, entry->offset, &kind, &size);
-       pack = (unsigned char *) p->pack_base + offset;
-       left = p->pack_size - offset;
        switch (kind) {
        case OBJ_DELTA:
-               retval = unpack_delta_entry(pack, size, left, type, sizep, p);
-               return retval;
+               return unpack_delta_entry(p, offset, size, type, sizep);
        case OBJ_COMMIT:
-               strcpy(type, commit_type);
-               break;
        case OBJ_TREE:
-               strcpy(type, tree_type);
-               break;
        case OBJ_BLOB:
-               strcpy(type, blob_type);
-               break;
        case OBJ_TAG:
-               strcpy(type, tag_type);
-               break;
+               strcpy(type, type_names[kind]);
+               *sizep = size;
+               return unpack_compressed_entry(p, offset, size);
        default:
                return NULL;
        }
-       *sizep = size;
-       retval = unpack_non_delta_entry(pack, size, left);
-       return retval;
 }
 
 int num_packed_objects(const struct packed_git *p)
@@ -1192,7 +1155,7 @@ int nth_packed_object_sha1(const struct packed_git *p, int n,
        void *index = p->index_base + 256;
        if (n < 0 || num_packed_objects(p) <= n)
                return -1;
-       memcpy(sha1, (char *) index + (24 * n) + 4, 20);
+       hashcpy(sha1, (unsigned char *) index + (24 * n) + 4);
        return 0;
 }
 
@@ -1206,10 +1169,10 @@ int find_pack_entry_one(const unsigned char *sha1,
 
        do {
                int mi = (lo + hi) / 2;
-               int cmp = memcmp((char *) index + (24 * mi) + 4, sha1, 20);
+               int cmp = hashcmp((unsigned char *)index + (24 * mi) + 4, sha1);
                if (!cmp) {
                        e->offset = ntohl(*((unsigned int *) ((char *) index + (24 * mi))));
-                       memcpy(e->sha1, sha1, 20);
+                       hashcpy(e->sha1, sha1);
                        e->p = p;
                        return 1;
                }
@@ -1322,7 +1285,7 @@ void *read_object_with_reference(const unsigned char *sha1,
        unsigned long isize;
        unsigned char actual_sha1[20];
 
-       memcpy(actual_sha1, sha1, 20);
+       hashcpy(actual_sha1, sha1);
        while (1) {
                int ref_length = -1;
                const char *ref_type = NULL;
@@ -1333,7 +1296,7 @@ void *read_object_with_reference(const unsigned char *sha1,
                if (!strcmp(type, required_type)) {
                        *size = isize;
                        if (actual_sha1_return)
-                               memcpy(actual_sha1_return, actual_sha1, 20);
+                               hashcpy(actual_sha1_return, actual_sha1);
                        return buffer;
                }
                /* Handle references */
@@ -1528,7 +1491,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
         */
        filename = write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);
        if (returnsha1)
-               memcpy(returnsha1, sha1, 20);
+               hashcpy(returnsha1, sha1);
        if (has_sha1_file(sha1))
                return 0;
        fd = open(filename, O_RDONLY);
@@ -1715,7 +1678,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
                unlink(tmpfile);
                return error("File %s corrupted", sha1_to_hex(sha1));
        }
-       if (memcmp(sha1, real_sha1, 20)) {
+       if (hashcmp(sha1, real_sha1)) {
                unlink(tmpfile);
                return error("File %s has bad hash", sha1_to_hex(sha1));
        }
@@ -1777,7 +1740,7 @@ int read_pipe(int fd, char** return_buf, unsigned long* return_size)
                        off += iret;
                        if (off == size) {
                                size *= 2;
-                               buf = realloc(buf, size);
+                               buf = xrealloc(buf, size);
                        }
                }
        } while (iret > 0);
index f567454d22ada41b1565f26e7136e62b70769dfa..3f6b77ccfadab14453a76b6654b50b186c9f5b25 100644 (file)
@@ -84,7 +84,7 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne
                        int cmp;
 
                        nth_packed_object_sha1(p, mid, now);
-                       cmp = memcmp(match, now, 20);
+                       cmp = hashcmp(match, now);
                        if (!cmp) {
                                first = mid;
                                break;
@@ -103,10 +103,10 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne
                                    !match_sha(len, match, next)) {
                                        /* unique within this pack */
                                        if (!found) {
-                                               memcpy(found_sha1, now, 20);
+                                               hashcpy(found_sha1, now);
                                                found++;
                                        }
-                                       else if (memcmp(found_sha1, now, 20)) {
+                                       else if (hashcmp(found_sha1, now)) {
                                                found = 2;
                                                break;
                                        }
@@ -120,7 +120,7 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne
                }
        }
        if (found == 1)
-               memcpy(sha1, found_sha1, 20);
+               hashcpy(sha1, found_sha1);
        return found;
 }
 
@@ -140,13 +140,13 @@ static int find_unique_short_object(int len, char *canonical,
        if (1 < has_unpacked || 1 < has_packed)
                return SHORT_NAME_AMBIGUOUS;
        if (has_unpacked != has_packed) {
-               memcpy(sha1, (has_packed ? packed_sha1 : unpacked_sha1), 20);
+               hashcpy(sha1, (has_packed ? packed_sha1 : unpacked_sha1));
                return 0;
        }
        /* Both have unique ones -- do they match? */
-       if (memcmp(packed_sha1, unpacked_sha1, 20))
+       if (hashcmp(packed_sha1, unpacked_sha1))
                return SHORT_NAME_AMBIGUOUS;
-       memcpy(sha1, packed_sha1, 20);
+       hashcpy(sha1, packed_sha1);
        return 0;
 }
 
@@ -159,7 +159,7 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
 
        if (len < MINIMUM_ABBREV)
                return -1;
-       memset(res, 0, 20);
+       hashclr(res);
        memset(canonical, 'x', 40);
        for (i = 0; i < len ;i++) {
                unsigned char c = name[i];
@@ -320,13 +320,13 @@ static int get_parent(const char *name, int len,
        if (parse_commit(commit))
                return -1;
        if (!idx) {
-               memcpy(result, commit->object.sha1, 20);
+               hashcpy(result, commit->object.sha1);
                return 0;
        }
        p = commit->parents;
        while (p) {
                if (!--idx) {
-                       memcpy(result, p->item->object.sha1, 20);
+                       hashcpy(result, p->item->object.sha1);
                        return 0;
                }
                p = p->next;
@@ -347,9 +347,9 @@ static int get_nth_ancestor(const char *name, int len,
 
                if (!commit || parse_commit(commit) || !commit->parents)
                        return -1;
-               memcpy(sha1, commit->parents->item->object.sha1, 20);
+               hashcpy(sha1, commit->parents->item->object.sha1);
        }
-       memcpy(result, sha1, 20);
+       hashcpy(result, sha1);
        return 0;
 }
 
@@ -401,7 +401,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
                o = deref_tag(o, name, sp - name - 2);
                if (!o || (!o->parsed && !parse_object(o->sha1)))
                        return -1;
-               memcpy(sha1, o->sha1, 20);
+               hashcpy(sha1, o->sha1);
        }
        else {
                /* At this point, the syntax look correct, so
@@ -413,7 +413,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
                        if (!o || (!o->parsed && !parse_object(o->sha1)))
                                return -1;
                        if (o->type == expected_type) {
-                               memcpy(sha1, o->sha1, 20);
+                               hashcpy(sha1, o->sha1);
                                return 0;
                        }
                        if (o->type == OBJ_TAG)
@@ -520,7 +520,7 @@ int get_sha1(const char *name, unsigned char *sha1)
                            memcmp(ce->name, cp, namelen))
                                break;
                        if (ce_stage(ce) == stage) {
-                               memcpy(sha1, ce->sha1, 20);
+                               hashcpy(sha1, ce->sha1);
                                return 0;
                        }
                        pos++;
index 0b89df6ddae5cfdfa4259379fc801f5e28f7c403..b006c5c9802d96bc504188e10a9698a1f943477c 100644 (file)
@@ -67,7 +67,7 @@ int fetch(unsigned char *sha1)
        signed char remote;
        struct object_list *temp;
 
-       if (memcmp(sha1, in_transit->item->sha1, 20)) {
+       if (hashcmp(sha1, in_transit->item->sha1)) {
                /* we must have already fetched it to clean the queue */
                return has_sha1_file(sha1) ? 0 : -1;
        }
index e5e0bb9d513016c25956e18230dd4ba21fb2445b..b7fcdb390c588545f2419ab3c825b924fbf96dd2 100755 (executable)
@@ -82,4 +82,8 @@ test_expect_failure \
     'do not move directory over existing directory' \
     'mkdir path0 && mkdir path0/path2 && git-mv path2 path0'
 
+test_expect_success \
+    'move into "."' \
+    'git-mv path1/path2/ .'
+
 test_done
index 916f489c5b79e04035f96dd9f667f70efedb83fa..7e2f4f088a359fe138b085730ba1b3465342e9e9 100644 (file)
@@ -39,8 +39,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
                show_entry(opt, "+", t2, base);
                return 1;
        }
-       if (!opt->find_copies_harder &&
-           !memcmp(sha1, sha2, 20) && mode1 == mode2)
+       if (!opt->find_copies_harder && !hashcmp(sha1, sha2) && mode1 == mode2)
                return 0;
 
        /*
index 3f83e98f3a443e4537f53abf32bcca1389c5d9d8..14cc5aea6c4eefbf4b0fa9c72ccb70ec550b44b4 100644 (file)
@@ -179,7 +179,7 @@ static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char
                if (cmp < 0)
                        break;
                if (entrylen == namelen) {
-                       memcpy(result, sha1, 20);
+                       hashcpy(result, sha1);
                        return 0;
                }
                if (name[entrylen] != '/')
@@ -187,7 +187,7 @@ static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char
                if (!S_ISDIR(*mode))
                        break;
                if (++entrylen == namelen) {
-                       memcpy(result, sha1, 20);
+                       hashcpy(result, sha1);
                        return 0;
                }
                return get_tree_entry(sha1, name + entrylen, result, mode);
diff --git a/tree.c b/tree.c
index ef456be9dd0faee46435a3c3b126a36c2be58051..ea386e506659c65224cfe55bdc4f8d086171637a 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -25,7 +25,7 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel
        ce->ce_flags = create_ce_flags(baselen + len, stage);
        memcpy(ce->name, base, baselen);
        memcpy(ce->name + baselen, pathname, len+1);
-       memcpy(ce->sha1, sha1, 20);
+       hashcpy(ce->sha1, sha1);
        return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
 }
 
index 43ed12484f6eb8bb828987872b2782182e579b9f..3ac0289b3a3309fca9ade4e271dbd8b0d2f148ea 100644 (file)
@@ -200,7 +200,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
 
                        any_files = 1;
 
-                       memcpy(ce->sha1, posns[i]->sha1, 20);
+                       hashcpy(ce->sha1, posns[i]->sha1);
                        src[i + o->merge] = ce;
                        subposns[i] = df_conflict_list;
                        posns[i] = posns[i]->next;
@@ -417,7 +417,7 @@ static int same(struct cache_entry *a, struct cache_entry *b)
        if (!a && !b)
                return 1;
        return a->ce_mode == b->ce_mode &&
-               !memcmp(a->sha1, b->sha1, 20);
+              !hashcmp(a->sha1, b->sha1);
 }
 
 
index fcf279843ad23b0605f3c2bc558e8d04a903554b..51ce936b060d34a2f759dba4f7aeeecf47a59a4b 100644 (file)
@@ -374,7 +374,7 @@ static int get_common_commits(void)
                                             sha1_to_hex(sha1),
                                             multi_ack ?  " continue" : "");
                                if (multi_ack)
-                                       memcpy(last_sha1, sha1, 20);
+                                       hashcpy(last_sha1, sha1);
                        }
                        continue;
                }
diff --git a/write_or_die.c b/write_or_die.c
new file mode 100644 (file)
index 0000000..ab4cb8a
--- /dev/null
@@ -0,0 +1,20 @@
+#include "cache.h"
+
+void write_or_die(int fd, const void *buf, size_t count)
+{
+       const char *p = buf;
+       ssize_t written;
+
+       while (count > 0) {
+               written = xwrite(fd, p, count);
+               if (written == 0)
+                       die("disk full?");
+               else if (written < 0) {
+                       if (errno == EPIPE)
+                               exit(0);
+                       die("write error (%s)", strerror(errno));
+               }
+               count -= written;
+               p += written;
+       }
+}
index 6a82da73b6d3b6b8cca23c3183cddc36c5cafb4b..08602f522183dc43787616f37cba9b8af4e3dade 100644 (file)
@@ -69,9 +69,9 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
        for (i = 0; i < nbuf; i++) {
                if (mb[i].ptr[mb[i].size-1] != '\n') {
                        /* Incomplete line */
-                       priv->remainder = realloc(priv->remainder,
-                                                 priv->remainder_size +
-                                                 mb[i].size);
+                       priv->remainder = xrealloc(priv->remainder,
+                                                  priv->remainder_size +
+                                                  mb[i].size);
                        memcpy(priv->remainder + priv->remainder_size,
                               mb[i].ptr, mb[i].size);
                        priv->remainder_size += mb[i].size;
@@ -83,9 +83,9 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
                        consume_one(priv, mb[i].ptr, mb[i].size);
                        continue;
                }
-               priv->remainder = realloc(priv->remainder,
-                                         priv->remainder_size +
-                                         mb[i].size);
+               priv->remainder = xrealloc(priv->remainder,
+                                          priv->remainder_size +
+                                          mb[i].size);
                memcpy(priv->remainder + priv->remainder_size,
                       mb[i].ptr, mb[i].size);
                consume_one(priv, priv->remainder,