diff options
86 files changed, 1210 insertions, 598 deletions
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 2e2acd72c7..c76cfffdc6 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -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 ------------- diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt index bfed945914..e1f89444a9 100644 --- a/Documentation/git-blame.txt +++ b/Documentation/git-blame.txt @@ -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. diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt index ae4c1a250e..c8a4c5a4d9 100644 --- a/Documentation/git-ls-remote.txt +++ b/Documentation/git-ls-remote.txt @@ -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 diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 7d86809844..b7b63f7136 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -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>. diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index 3ae6e74573..41bb7e12e3 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -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 index 0000000000..2e9d981247 --- /dev/null +++ b/Documentation/git-zip-tree.txt @@ -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 + diff --git a/Documentation/git.txt b/Documentation/git.txt index 3de5fa9c82..a9c87e38da 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -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 ----------- diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt index cb482bf98e..23be0050b0 100644 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.txt @@ -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 --- @@ -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 @@ -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; } diff --git a/builtin-apply.c b/builtin-apply.c index 0b00a98aa1..b47ccacc2e 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -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) diff --git a/builtin-cat-file.c b/builtin-cat-file.c index df009ade7a..6c16bfa1ae 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -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; } diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index 6b55f931cb..b097c888a0 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -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; diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index 9c98796671..e2e690a1ae 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -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; } diff --git a/builtin-diff-stages.c b/builtin-diff-stages.c index 5960e08997..70bb89808d 100644 --- a/builtin-diff-stages.c +++ b/builtin-diff-stages.c @@ -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, diff --git a/builtin-diff.c b/builtin-diff.c index 40e5c96f30..a6590205e8 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -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; diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index 28b5dfd054..a5ed8dbbac 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -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; diff --git a/builtin-grep.c b/builtin-grep.c index 0bd517b264..8213ce2402 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -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); } diff --git a/builtin-log.c b/builtin-log.c index 691cf3aef7..fbc58bbcab 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -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; diff --git a/builtin-mv.c b/builtin-mv.c index c0c8764f7f..4d21d88412 100644 --- a/builtin-mv.c +++ b/builtin-mv.c @@ -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 @@ next: } } 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 @@ next: } 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); } diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 448461bc48..46f524dfc3 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -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) diff --git a/builtin-push.c b/builtin-push.c index 2b5e6fa9ed..ada8338cc1 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -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; diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 53087faf7a..c1867d2a00 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -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; diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 95fbf77fad..18786f88e3 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -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) || diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index 215892b696..61a413590d 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -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")) { diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 63f4b8e45d..ca0ebc2585 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -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); diff --git a/builtin-update-index.c b/builtin-update-index.c index 9f0cf28ba2..0620e779b0 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -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) diff --git a/builtin-update-ref.c b/builtin-update-ref.c index 5bd71825fd..90a3da53ad 100644 --- a/builtin-update-ref.c +++ b/builtin-update-ref.c @@ -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); diff --git a/builtin-write-tree.c b/builtin-write-tree.c index ca06149f18..50670dc7bf 100644 --- a/builtin-write-tree.c +++ b/builtin-write-tree.c @@ -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 index 0000000000..a5b834d360 --- /dev/null +++ b/builtin-zip-tree.c @@ -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; +} @@ -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); diff --git a/cache-tree.c b/cache-tree.c index d9f7e1e3dd..323c68a670 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -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; } @@ -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); diff --git a/combine-diff.c b/combine-diff.c index ce063b4ffa..46d9121baf 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -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); } @@ -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' */ @@ -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; diff --git a/contrib/gitview/gitview.txt b/contrib/gitview/gitview.txt index 6924df286e..77c29de305 100644 --- a/contrib/gitview/gitview.txt +++ b/contrib/gitview/gitview.txt @@ -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 diff --git a/convert-objects.c b/convert-objects.c index 168771ed85..631678b08a 100644 --- a/convert-objects.c +++ b/convert-objects.c @@ -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; diff --git a/csum-file.c b/csum-file.c index e2278897d0..b7174c6c05 100644 --- a/csum-file.c +++ b/csum-file.c @@ -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)) @@ -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) @@ -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]); diff --git a/describe.c b/describe.c index 2b9301fc12..5dd8b2e397 100644 --- a/describe.c +++ b/describe.c @@ -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 diff --git a/diff-delta.c b/diff-delta.c index 7da9205a5d..fa16d06c8d 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -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; diff --git a/diff-lib.c b/diff-lib.c index 116b5a9d68..9edfa92626 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -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; @@ -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 { diff --git a/diffcore-break.c b/diffcore-break.c index ed0e14c6d8..acb18db1db 100644 --- a/diffcore-break.c +++ b/diffcore-break.c @@ -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)) diff --git a/diffcore-rename.c b/diffcore-rename.c index 0ec488a903..ef239012b6 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -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; @@ -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); diff --git a/dump-cache-tree.c b/dump-cache-tree.c index 1ccaf51773..1f73f1ea7d 100644 --- a/dump-cache-tree.c +++ b/dump-cache-tree.c @@ -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) "); @@ -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); } - - diff --git a/environment.c b/environment.c index e6bd0033b4..5fae9ac305 100644 --- a/environment.c +++ b/environment.c @@ -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(); diff --git a/fetch-pack.c b/fetch-pack.c index e18c1489a1..377feded1c 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -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, @@ -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)); diff --git a/fsck-objects.c b/fsck-objects.c index 31e00d84b3..ae0ec8d039 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -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(); diff --git a/git-cherry.sh b/git-cherry.sh index f0e8831fa4..8832573fee 100755 --- a/git-cherry.sh +++ b/git-cherry.sh @@ -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 diff --git a/git-compat-util.h b/git-compat-util.h index b2e18954c0..91f2b0d3f0 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -172,7 +172,4 @@ static inline int sane_case(int x, int high) return x; } -#ifndef MAXPATHLEN -#define MAXPATHLEN 256 -#endif #endif diff --git a/git-reset.sh b/git-reset.sh index 36fc8ce25b..3133b5bd25 100755 --- a/git-reset.sh +++ b/git-reset.sh @@ -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 diff --git a/git-send-email.perl b/git-send-email.perl index a83c7e9094..746c525079 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -510,7 +510,7 @@ foreach my $t (@files) { 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", diff --git a/git-svn.perl b/git-svn.perl index 0d58bb9b37..0290850b66 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -51,7 +51,8 @@ my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit, $_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; @@ -118,6 +119,11 @@ my %cmd = ( { '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 ######################### @@ -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); diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7c92ac30ce..966c54a63c 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -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 @@ HTML 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; diff --git a/http-fetch.c b/http-fetch.c index 7f07d2a967..7619b338fe 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -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", diff --git a/http-push.c b/http-push.c index 2bd9845765..04cb238e96 100644 --- a/http-push.c +++ b/http-push.c @@ -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; diff --git a/index-pack.c b/index-pack.c index b20659c259..80bc6cb45b 100644 --- a/index-pack.c +++ b/index-pack.c @@ -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) diff --git a/merge-tree.c b/merge-tree.c index 7cf00be6d5..c2e9a867ed 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -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; } @@ -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); @@ -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(); diff --git a/pack-check.c b/pack-check.c index 3a62e1b7e4..04c6c00821 100644 --- a/pack-check.c +++ b/pack-check.c @@ -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); diff --git a/pack-redundant.c b/pack-redundant.c index 92a09ed362..edb5524fc4 100644 --- a/pack-redundant.c +++ b/pack-redundant.c @@ -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 @@ redo_from_start: 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++; diff --git a/patch-id.c b/patch-id.c index 3b4c80f764..086d2d9c68 100644 --- a/patch-id.c +++ b/patch-id.c @@ -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; } diff --git a/read-cache.c b/read-cache.c index 6bec833eec..b6982eac41 100644 --- a/read-cache.c +++ b/read-cache.c @@ -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; } diff --git a/receive-pack.c b/receive-pack.c index 81e91909b8..201531626c 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -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; @@ -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", diff --git a/revision.c b/revision.c index 5a91d06b98..1d89d72738 100644 --- a/revision.c +++ b/revision.c @@ -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; diff --git a/send-pack.c b/send-pack.c index 43e10b0a62..fd79a61923 100644 --- a/send-pack.c +++ b/send-pack.c @@ -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; diff --git a/sha1_file.c b/sha1_file.c index 18dece46b1..46272b5916 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -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); diff --git a/sha1_name.c b/sha1_name.c index f567454d22..3f6b77ccfa 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -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++; diff --git a/ssh-fetch.c b/ssh-fetch.c index 0b89df6dda..b006c5c980 100644 --- a/ssh-fetch.c +++ b/ssh-fetch.c @@ -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; } diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index e5e0bb9d51..b7fcdb390c 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -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 diff --git a/tree-diff.c b/tree-diff.c index 916f489c5b..7e2f4f088a 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -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; /* diff --git a/tree-walk.c b/tree-walk.c index 3f83e98f3a..14cc5aea6c 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -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); @@ -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); } diff --git a/unpack-trees.c b/unpack-trees.c index 43ed12484f..3ac0289b3a 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -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); } diff --git a/upload-pack.c b/upload-pack.c index fcf279843a..51ce936b06 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -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 index 0000000000..ab4cb8a69c --- /dev/null +++ b/write_or_die.c @@ -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; + } +} diff --git a/xdiff-interface.c b/xdiff-interface.c index 6a82da73b6..08602f5221 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -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, |