--------
[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
-----------
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
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::
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.
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
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:
* `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
-------------
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).
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.
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
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
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
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
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
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
~~~~~~~~~~~~~~
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
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.
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.
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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>.
[--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]
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.
--- /dev/null
+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
+
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
-----------
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
--------
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
---
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 = \
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
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++) {
if (i == 20)
return -1;
- memcpy(sha1, blob_sha1, 20);
+ hashcpy(sha1, blob_sha1);
return 0;
}
strcmp(blame_file + baselen, pathname))
return -1;
- memcpy(blob_sha1, sha1, 20);
+ hashcpy(blob_sha1, sha1);
return -1;
}
* form.
*/
for (len = 0 ; ; len++) {
- char c = name[len];
-
- switch (c) {
+ switch (name[len]) {
default:
continue;
case '\n':
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)
#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. */
/* 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
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;
}
* 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)
if (!buf)
die("git-cat-file %s: bad file", argv[2]);
- flush_buffer(buf, size);
+ write_or_die(1, buf, size);
return 0;
}
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;
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;
}
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,
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) {
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;
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;
{
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;
*/
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);
}
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;
continue;
nr++;
- list = realloc(list, nr * sizeof(list[0]));
+ list = xrealloc(list, nr * sizeof(list[0]));
list[nr - 1] = commit;
}
total = nr;
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) {
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);
/* 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) {
/*
" 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) {
}
} 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) {
} 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);
}
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;
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)
*/
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;
}
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;
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;
}
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;
}
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)
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;
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:
case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
die("%s died with strange error", sender);
default:
- return -error;
+ return -err;
}
}
return 0;
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;
/* 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);
}
{
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) ||
#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;
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;
}
}
write_if_needed();
}
while (size >= BLOCKSIZE) {
- reliable_write(buf, BLOCKSIZE);
+ write_or_die(1, buf, BLOCKSIZE);
size -= BLOCKSIZE;
buf += BLOCKSIZE;
}
{
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);
}
}
}
}
-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")) {
{
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;
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);
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);
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);
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);
}
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];
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);
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);
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 */
}
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)
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);
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);
--- /dev/null
+/*
+ * 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;
+}
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);
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
#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++) {
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;
}
#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);
{
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);
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);
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);
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;
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;
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;
}
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);
}
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;
};
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)
}
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' */
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;
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;
}
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;
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
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++;
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) {
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)
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;
}
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))
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)
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)
"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,
*/
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;
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]);
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) {
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
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;
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;
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);
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 =
}
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;
{
if (mode) {
spec->mode = canon_mode(mode);
- memcpy(spec->sha1, sha1, 20);
+ hashcpy(spec->sha1, sha1);
spec->sha1_valid = !is_null_sha1(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
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) {
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;
}
}
}
else
- memset(one->sha1, 0, 20);
+ hashclr(one->sha1);
}
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,
* 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. */
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 {
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))
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;
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;
}
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);
}
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) ");
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;
create_directories(path, state);
return write_entry(ce, path, state, 0);
}
-
-
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);
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();
continue;
}
- memcpy(ref->new_sha1, local, 20);
+ hashcpy(ref->new_sha1, local);
if (!verbose)
continue;
fprintf(stderr,
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));
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();
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
return x;
}
-#ifndef MAXPATHLEN
-#define MAXPATHLEN 256
-#endif
#endif
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
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",
$_message, $_file, $_follow_parent, $_no_metadata,
$_template, $_shared, $_no_default_regex, $_no_graft_copy,
$_limit, $_verbose, $_incremental, $_oneline, $_l_fmt, $_show_commit,
- $_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m);
+ $_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m,
+ $_merge, $_strategy, $_dry_run);
my (@_branch_from, %tree_map, %users, %rusers, %equiv);
my ($_svn_co_url_revs, $_svn_pg_peg_revs);
my @repo_path_split_cache;
{ 'message|m=s' => \$_message,
'file|F=s' => \$_file,
%cmt_opts } ],
+ dcommit => [ \&dcommit, 'Commit several diffs to merge with upstream',
+ { 'merge|m|M' => \$_merge,
+ 'strategy|s=s' => \$_strategy,
+ 'dry-run|n' => \$_dry_run,
+ %cmt_opts } ],
);
my $cmd;
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);
# 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,
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();
} else {
$ed->close_edit;
}
+ $_message = $_file = undef;
}
########################### utility functions #########################
; /* 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 == '"')) {
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;
{ "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 },
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);
<?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"/>
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;
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;
}
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;
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);
} 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",
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 =
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;
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;
}
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;
if (*symref != NULL)
free(*symref);
*symref = NULL;
- memset(sha1, 0, 20);
+ hashclr(sha1);
if (buffer.posn == 0)
return;
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;
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;
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);
}
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:
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) {
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;
{
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)
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);
{
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)
{
return a->sha1 &&
b->sha1 &&
- !memcmp(a->sha1, b->sha1, 20) &&
+ !hashcmp(a->sha1, b->sha1) &&
a->mode == b->mode;
}
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);
}
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);
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)
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();
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);
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);
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);
}
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 */
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,
{
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++;
if (!get_sha1_hex(p, n)) {
flush_current_id(patchlen, sha1, &ctx);
- memcpy(sha1, n, 20);
+ hashcpy(sha1, n);
patchlen = 0;
continue;
}
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;
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;
}
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;
if (lstat(path, &st) < 0) {
if (reading || errno != ENOENT)
return NULL;
- memset(sha1, 0, 20);
+ hashclr(sha1);
return path;
}
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);
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;
}
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",
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",
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;
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;
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;
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;
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())
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);
}
}
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;
}
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;
}
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)
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;
}
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);
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;
}
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",
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",
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));
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);
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)
{
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)
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;
}
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;
}
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;
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 */
*/
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);
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));
}
off += iret;
if (off == size) {
size *= 2;
- buf = realloc(buf, size);
+ buf = xrealloc(buf, size);
}
}
} while (iret > 0);
int cmp;
nth_packed_object_sha1(p, mid, now);
- cmp = memcmp(match, now, 20);
+ cmp = hashcmp(match, now);
if (!cmp) {
first = mid;
break;
!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;
}
}
}
if (found == 1)
- memcpy(sha1, found_sha1, 20);
+ hashcpy(sha1, found_sha1);
return found;
}
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;
}
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];
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;
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;
}
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
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)
memcmp(ce->name, cp, namelen))
break;
if (ce_stage(ce) == stage) {
- memcpy(sha1, ce->sha1, 20);
+ hashcpy(sha1, ce->sha1);
return 0;
}
pos++;
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;
}
'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
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;
/*
if (cmp < 0)
break;
if (entrylen == namelen) {
- memcpy(result, sha1, 20);
+ hashcpy(result, sha1);
return 0;
}
if (name[entrylen] != '/')
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);
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);
}
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;
if (!a && !b)
return 1;
return a->ce_mode == b->ce_mode &&
- !memcmp(a->sha1, b->sha1, 20);
+ !hashcmp(a->sha1, b->sha1);
}
sha1_to_hex(sha1),
multi_ack ? " continue" : "");
if (multi_ack)
- memcpy(last_sha1, sha1, 20);
+ hashcpy(last_sha1, sha1);
}
continue;
}
--- /dev/null
+#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;
+ }
+}
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;
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,