Compare commits

...

537 Commits

Author SHA1 Message Date
7685227e97 GIT 1.5.1-rc3 2007-03-28 15:58:09 -07:00
43a8e4fe8e Update main git.html page to point at 1.5.0.6 documentation
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-28 15:40:17 -07:00
0a98f9d138 Merge branch 'maint' to synchronize with 1.5.0.6 2007-03-28 15:39:57 -07:00
03bcaacaad t/t6006: add tests for a slightly more complex commit messages
Especially this tests i18n messages and encoding header.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-28 14:28:00 -07:00
6a5ea2d023 Fix "--pretty=format:" encoding item
It printed the header "encoding " instead of just showing
the encoding, as all other items do.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-28 14:27:43 -07:00
542e165cdc Fix "--pretty=format:" for parent related items.
There are two breakages in the %P/%p interpolation.  It appended
an excess SP at the end of the list, and it gave uninitialized
contents of a buffer on the stack for root commits.

This fixes it, while updating the t6006 test which expected the
wrong output.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-28 13:44:04 -07:00
9c880b3ea5 http-fetch: remove path_len from struct alt_base, it was computed but never used
Signed-off-by: Gerrit Pape <pape@smarden.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-28 04:44:23 -07:00
2afea3bcd2 http-fetch: don't use double-slash as directory separator in URLs
Please see http://bugs.debian.org/409887

http-fetch expected the URL given at the command line to have a trailing
slash anyway, and then added '/objects...' when requesting objects files
from the http server.

Now it doesn't require the trailing slash in <url> anymore, and strips
trailing slashes if given nonetheless.

Signed-off-by: Gerrit Pape <pape@smarden.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-28 04:44:16 -07:00
fa21b60232 Add some basic tests of rev-list --pretty=format
These could stand to be a little more complex, but it should
at least catch obvious problems (like the recently fixed %ct
bug).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 18:57:01 -07:00
465b3518a9 git-upload-pack: make sure we close unused pipe ends
Right now, we don't close the read end of the pipe when git-upload-pack
runs git-pack-object, so we hang forever (why don't we get SIGALRM?)
instead of dying with SIGPIPE if the latter dies, which seems to be the
norm if the client disconnects.

Thanks to Johannes Schindelin <Johannes.Schindelin@gmx.de> for
pointing out where this close() needed to go.

This patch has been tested on kernel.org for several weeks and appear
to resolve the problem of git-upload-pack processes hanging around
forever.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 17:05:12 -07:00
4621af3716 --pretty=format: fix broken %ct and %at interpolation
A pointer arithmetic error in fill_person caused random data
from the commit object to be included with the timestamp,
which looked something like:

    $ git-rev-list --pretty=format:%ct origin/next | head
    commit 98453bdb3db10db26099749bc4f2dc029bed9aa9
    1174977948 -0700

    Merge branch 'master' into next

    * master:
      Bisect: Use
    commit c0ce981f5e
    1174889646 -0700

Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 17:04:26 -07:00
c6e0caa384 use xrealloc in help.c
Signed-off-by: James Bowes <jbowes@dangerouslyinc.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 16:57:57 -07:00
aa4cfa8516 read-tree: use xcalloc
Signed-off-by: James Bowes <jbowes@dangerouslyinc.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 16:57:26 -07:00
608d48b220 Fix "getaddrinfo()" buglet
At least in Linux glibc, "getaddrinfo()" has a very irritating feature (or
bug, who knows..).

Namely if you pass it in an empty string for the service name, it will
happily and quietly consider it identical to a NULL port pointer, and
return port number zero and no errors. Which obviously will not work.

Maybe that's what it's really expected to do, although the man-page for
getaddrinfo() certainly implies that it's a bug.

So when somebody passes me a "please pull" request pointing to something
like the following

	git://git.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git

(note the extraneous colon at the end of the host name), git would happily
try to connect to port 0, which would generally just cause the remote to
not even answer, and the "connect()" will take a long time to time out.

So to work around the glibc feature/bug, just notice this empty port case
automatically. Also, add the port information to the error information
when it fails to look up (maybe it's the host-name that fails, maybe it's
the port-name - we should print out both).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 13:00:13 -07:00
66d5871ead Makefile: remove test-chmtime program in target clean.
While running 'make test', the test-chmtime program is created, and should
be cleaned up on 'make clean'.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:58:46 -07:00
f73bbb2d0c gitweb: Cleanup and uniquify die_error calls
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:58:23 -07:00
e82973cfb0 sha1_file.c (write_sha1_file): Detect close failure
This is in the same spirit as earlier fix to write_sha1_from_fd().

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:56:01 -07:00
b704e589f4 git.el: Display some information about the HEAD commit.
Use git-log --pretty=oneline to print a short description of the
current HEAD (and merge heads if any) in the buffer header.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:52:41 -07:00
89d5892389 Document git-log --first-parent
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:51:13 -07:00
8302012097 Bisect: add checks at the beginning of "git bisect run".
We may be able to "run" with only one good revision given
and then verify that the result of the first run is bad.
And perhaps also the other way around.

But for now let's check that we have at least one bad and
one good revision before we start to run.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:48:30 -07:00
0d315468f3 sha1_file.c (write_sha1_from_fd): Detect close failure.
I stumbled across this in the context of the fchmod 0444 patch.
At first, I was going to unlink and call error like the two subsequent
tests do, but a failed write (above) provokes a "die", so I made
this do the same.  This is testing for a write failure, after all.

Signed-off-by: Jim Meyering <jim@meyering.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:43:49 -07:00
e4d9516b21 git-rm: don't remove newly added file without -f
Given this set of commands:

  $ echo "newly added file" >new
  $ git add new
  $ git rm new

the file "new" was previously removed from the working
directory and the index. Because it was not in HEAD, it is
available only by searching for unreachable objects.

Instead, we now err on the safe side and refuse to remove
a file which is not referenced by HEAD.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-27 12:43:39 -07:00
c0ce981f5e Bisect: Use "git-show-ref --verify" when reseting.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-25 23:14:06 -07:00
52c813f22f gitweb: Add example of config file and how to generate projects list to gitweb/INSTALL
Add simple example of config file (turning on and allowing override of
a few %features). Also example config file and script to generate list
of projects in a format that can be used as GITWEB_LIST / $projects_list.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-25 22:22:33 -07:00
b6da18b1d1 GIT 1.5.1-rc2
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-25 18:01:50 -07:00
0b59451c1b git-svn: fix rel_path() when not connected to the repository root
This should fix fetching for people who did not use
"git svn --minimize" or cannot connect to the repository root
due to the lack of permissions.

I'm not sure what I was on when I made the change to the
rel_path() function in 4e9f6cc78e
that made it die() when we weren't connected to the repository
root :x

Thanks to Sven Verdoolaege for reporting this bug.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-25 18:01:28 -07:00
3301521a25 use xmalloc in git.c and help.c
Signed-off-by: James Bowes <jbowes@dangerouslyinc.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-25 18:00:23 -07:00
3a81b9f571 Merge branch 'jc/fpl'
* jc/fpl:
  git-log --first-parent: show only the first parent log
2007-03-25 17:47:07 -07:00
620d3f4216 Update README to point at a few key periodical messages to the list
They give a good starting point to new people who want to get
involved.  This owes suggestions by Martin Langhoff and Steven
Grimm.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-25 17:42:32 -07:00
2603fa5fb3 Merge branch 'maint'
* maint:
  user-manual: introduce "branch" and "branch head" differently
  glossary: clean up cross-references
  glossary: stop generating automatically
  user-manual: Use def_ instead of ref_ for glossary references.
  user-manual.txt: fix a tiny typo.
  user-manual: run xsltproc without --nonet option
2007-03-25 15:08:11 -07:00
c5a07b3b4f Merge branch 'js/remote-show-push'
* js/remote-show-push:
  Teach git-remote to list pushed branches.
2007-03-25 01:45:06 -07:00
12d6697f3a Merge branch 'maint'
* maint:
  gitweb: Add some installation notes in gitweb/INSTALL
  gitweb: Fix not marking signoff lines in "log" view
  gitweb: Don't escape attributes in CGI.pm HTML methods
  gitweb: Change to use explicitly function call cgi->escapHTML()
2007-03-25 00:21:40 -07:00
06aff47b22 Use diff* with --exit-code in git-am, git-rebase and git-merge-ours
This simplifies the shell code, reduces its memory footprint, and
speeds things up. The performance improvements should be noticable
when git-rebase works on big commits.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-24 23:01:36 -07:00
2a18c266d0 Document --quiet option to git-diff
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-24 22:32:55 -07:00
b5b8d8141a write_sha1_from_fd() should make new objects read-only
... like it is done everywhere else.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-24 22:32:41 -07:00
0e55181f29 make it more obvious that temporary files are temporary files
When some operations are interrupted (or "die()'d" or crashed) then the
partial object/pack/index file may remain around.  Make it more obvious
in their name that those files are temporary stuff and can be cleaned up
if no operation is in progress.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-24 22:32:39 -07:00
46d409d0bf update-hook: remove e-mail sending hook.
The update hook's only job is to decide is a particular update
is allowed or not.  It was not the right place to send out
update notification e-mails from to begin with, as the final
stage of updating refs can fail after this hook runs.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-24 22:30:53 -07:00
2499857b0b git-am documentation: describe what is taken from where.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-24 03:08:54 -07:00
e43b010582 git-revert: Revert revert message to old behaviour
When converting from the shell script, based on a misreading of the
sed invocation, the builtin included the abbreviated commit name,
and did _not_ include the quotes around the oneline message.

This fixes it.

[jc: with a fix for the typo/thinko spotted by Linus, and also
 removing the unwanted abbrev at the beginning.]

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-24 02:50:22 -07:00
b08bbae7e1 Merge branch 'maint'
* maint:
  gitweb: Fix "next" link in commit view
2007-03-23 23:29:37 -07:00
6cea055547 Documentation: bisect: make a comment fit better in the man page.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 23:29:29 -07:00
1207f9e705 Documentation: bisect: add some titles to some paragraphs.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 23:29:09 -07:00
fed820ad56 Documentation: bisect: reformat more paragraphs.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 23:26:11 -07:00
cc070d1f79 Documentation: bisect: reword one paragraph.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 23:26:02 -07:00
7891a2811d Documentation: bisect: reformat some paragraphs.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 23:25:54 -07:00
a4e9d71edb Fix path-limited "rev-list --bisect" termination condition.
In a path-limited bisection, when the $bad commit is not
changing the limited path, and the number of suspects is 1, the
code miscounted and returned $bad from find_bisection(), which
is not marked with TREECHANGE.  This is of course filtered by
the output routine, resulting in an empty output, in turn
causing git-bisect driver to say "$bad was both good and bad".

Illustration.  Suppose you have these four commits, and only C
changes path P.  You know D is bad and A is good.

	A---B---C*--D

git-bisect driver runs this to find a bisection point:

	$ git rev-list --bisect A..D -- P

which calls find_bisection() with B, C and D.  The set of
commits that is given to this function is the same set of
commits as rev-list without --bisect option and pathspec
returns.  Among them, only C is marked with TREECHANGE.  Let's
call the set of commits given to find_bisection() that are
marked with TREECHANGE (or all of them if no path limiter is in
effect) "the bisect set".  In the above example, the size of the
bisect set is 1 (contains only "C").

For each commit in its input, find_bisection() computes the
number of commits it can reach in the bisect set.  For a commit
in the bisect set, this number includes itself, so the number is
1 or more.  This number is called "depth", and computed by
count_distance() function.

When you have a bisect set of N commits, and a commit has depth
D, how good is your bisection if you returned that commit?  How
good this bisection is can be measured by how many commits are
effectively tested "together" by testing one commit.

Currently you have (N-1) untested commits (the tip of the bisect
set, although it is included in the bisect set, is already known
to be bad).  If the commit with depth D turns out to be bad,
then your next bisect set will have D commits and you will have
(D-1) untested commits left, which means you tested (N-1)-(D-1)
= (N-D) commits with this bisection.  If it turns out to be good, then
your next bisect set will have (N-D) commits, and you will have
(N-D-1) untested commits left, which means you tested
(N-1)-(N-D-1) = D commits with this bisection.

Therefore, the goodness of this bisection is is min(N-D, D), and
find_bisection() function tries to find a commit that maximizes
this, by initializing "closest" variable to 0 and whenever a
commit with the goodness that is larger than the current
"closest" is found, that commit and its goodness are remembered
by updating "closest" variable.  The "the commit with the best
goodness so far" is kept in "best" variable, and is initialized
to a commit that happens to be at the beginning of the list of
commits given to this function (which may or may not be in the
bisect set when path-limit is in use).

However, when N is 1, then the sole tree-changing commit has
depth of 1, and min(N-D, D) evaluates to 0.  This is not larger
than the initial value of "closest", and the "so far the best
one" commit is never replaced in the loop.

When path-limit is not in use, this is not a problem, as any
commit in the input set is tree-changing.  But when path-limit
is in use, and when the starting "bad" commit does not change
the specified path, it is not correct to return it.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 17:20:43 -07:00
12cb813733 git-bisect.sh: properly dq $GIT_DIR
Otherwise you would be in trouble if your GIT_DIR has IFS letters in it.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 13:29:55 -07:00
673e58389f git-bisect: typofix
The branch you are on while bisecting is always "bisect", and
checking for "refs/heads/bisect*" is wrong.  Only check if it is
exactly "refs/heads/bisect".

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 13:15:21 -07:00
abba9dbbf4 checkout: report where the new HEAD is upon detaching HEAD
After "git reset" moves the HEAD around, it reports which commit
you are on, which gives the user a warm fuzzy feeling of
assurance.  Give the same assurance from git-checkout when
moving the detached HEAD around.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 02:48:09 -07:00
a17c410100 Bisect: implement "git bisect run <cmd>..." to automatically bisect.
This idea was suggested by Bill Lear
(Message-ID: <17920.38942.364466.642979@lisa.zopyra.com>)
and I think it is a very good one.

This patch adds a new test file for "git bisect run", but there
is currently only one basic test.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 01:54:47 -07:00
cc65343a84 Bisect: convert revs given to good and bad to commits
Without this the rev could be (e.g.) a tag and then the condition to end the
bisect might fail and you have to check the already known to be bad revision
once more.

Signed-off-by: Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-23 01:48:29 -07:00
3007a78033 t4118: be nice to non-GNU sed
Elias Pipping:
> I'm on a mac, hence /usr/bin/sed is not gnu sed, which makes
> t4118 fail.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Ack'd-by: Elias Pipping <pipping@macports.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 18:08:37 -07:00
cc96fd092a git-apply: Do not free the wrong buffer when we convert the data for writeout
When we write out the result of patch application, we sometimes
need to munge the data (e.g. under core.autocrlf).  After doing
so, what we should free is the temporary buffer that holds the
converted data returned from convert_to_working_tree(), not the
original one.

This patch also moves the call to open() up in the function, as
the caller expects us to fail cheaply if leading directories
need to be created (and then the caller creates them and calls
us again).  For that calling pattern, attempting conversion
before opening the file adds unnecessary overhead.

Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 17:32:51 -07:00
00cec846f1 Merge git://git2.kernel.org/pub/scm/gitk/gitk
* git://git2.kernel.org/pub/scm/gitk/gitk:
  [PATCH] prefer "git COMMAND" over "git-COMMAND" in gitk
2007-03-22 03:05:34 -07:00
aa576e6b47 Merge branch 'maint'
* maint:
  Documentation/pack-format.txt: Clear up description of types.
  fix typo in git-am manpage
2007-03-22 03:05:25 -07:00
605fac8b5b update HEAD reflog when branch pointed to by HEAD is directly modified
The HEAD reflog is updated as well as the reflog for the branch pointed
to by HEAD whenever it is referenced with "HEAD".

There are some cases where a specific branch may be modified directly.
In those cases, the HEAD reflog should be updated as well if it is a
symref to that branch in order to be consistent.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 03:02:48 -07:00
0a0d080bdc update-hook: abort early if the project description is unset
It was annoying to always have the first email from a project be from
the "Unnamed repository; edit this file to name it for gitweb project";
just because it's so easy to forget to set it.

This patch checks to see if the description file is still default (or
empty) and aborts if so - allowing you to fix the problem before sending
out silly looking emails to every developer.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 03:02:31 -07:00
85295a52e6 git-merge: Put FETCH_HEAD data in merge commit message
This makes git-fetch <URL> && git-merge FETCH_HEAD produce the
same merge message as git-pull <URL>.

Signed-off-by: Michael S. Tsirkin <mst@dev.mellanox.co.il>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 03:01:43 -07:00
a1bf91e081 git-rebase: make 'rebase HEAD branch' work as expected.
When you want to amend the commit message of 3 commits before
the tip of the current branch, say 'master',

	A--B--C--D--E(master)

it is sometimes handy to make your head detached at that commit
with:

	$ git checkout HEAD~3 ;# check out B
	$ git commit --amend ;# without modifying contents...

to create:

          .B'(HEAD)
         /
	A--B--C--D--E(master)

and then rebase 'master' branch onto HEAD with this:

	$ git rebase HEAD master

to result in:

          .B'-C'-D'-E(master=HEAD)
         /
	A--B--C--D--E

However, the current code interprets HEAD after it switches to
the branch 'master', which means the rebase will not do
anything.  You have to say something unwieldly like this
instead:

	$ git rebase $(git rev-parse HEAD) master

This fixes it by expanding the $onto commit name before
switching to the target branch.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 02:56:53 -07:00
1d848f643c tree_entry_interesting(): allow it to say "everything is interesting"
In addition to optimizing pathspecs that would never match,
which was done earlier, this optimizes pathspecs that would
always match (e.g. "arch/" while the traversal is already in
"arch/i386/" hierarchy).

This patch makes the worst case slightly more palatable, while
improving average case.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 00:36:00 -07:00
ccc744abbb tree-diff: avoid strncmp()
If we already know that some of the pathspecs can match later
entries in the tree we are looking at, we do not have to do more
expensive strncmp() upfront before comparing the length of the
match pattern and the path, as a path longer than the match
pattern will not match it, and a path shorter than the match
pattern will match only if the path is a directory-component
wise prefix of the match pattern.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 00:34:39 -07:00
7d2f667b12 Teach tree_entry_interesting() that the tree entries are sorted.
When we are looking at a tree entry with pathspecs, if all the
pathspecs sort strictly earlier than the entry we are currently
looking at, there is no way later entries in the same tree would
match our pathspecs, because the entries are sorted.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-22 00:29:49 -07:00
4651ece854 Switch over tree descriptors to contain a pre-parsed entry
This makes the tree descriptor contain a "struct name_entry" as part of
it, and it gets filled in so that it always contains a valid entry. On
some benchmarks, it improves performance by up to 15%.

That makes tree entry "extract" trivial, and means that we only actually
need to decode each tree entry just once: we decode the first one when
we initialize the tree descriptor, and each subsequent one when doing
"update_tree_entry()".  In particular, this means that we don't need to
do strlen() both at extract time _and_ at update time.

Finally, it also allows more sharing of code (entry_extract(), that
wanted a "struct name_entry", just got totally trivial, along with the
"tree_entry()" function).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-21 11:15:26 -07:00
6fda5e5180 Initialize tree descriptors with a helper function rather than by hand.
This removes slightly more lines than it adds, but the real reason for
doing this is that future optimizations will require more setup of the
tree descriptor, and so we want to do it in one place.

Also renamed the "desc.buf" field to "desc.buffer" just to trigger
compiler errors for old-style manual initializations, making sure I
didn't miss anything.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-21 10:21:57 -07:00
a8c40471ab Remove "pathlen" from "struct name_entry"
Since we have the "tree_entry_len()" helper function these days, and
don't need to do a full strlen(), there's no point in saving the path
length - it's just redundant information.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-21 10:21:56 -07:00
1ce09dd678 [PATCH] prefer "git COMMAND" over "git-COMMAND" in gitk
Preferring git _space_ COMMAND over git _dash_ COMMAND allows the
user to have only git and gitk in their path. e.g. when git and gitk
are symbolic links in a personal bin directory to the real git and gitk.

Signed-off-by: Paul Mackerras <paulus@samba.org>
2007-03-21 22:02:19 +11:00
171dccd511 blame: cmp_suspect is not "cmp" anymore.
The earlier round makes the function return "is it different"
and it does not return a value suitable for sorting anymore.  Reverse
the logic to return "are they the same suspect" instead, and rename
it to "same_suspect()".

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 23:37:51 -07:00
3254d218b4 minor git-prune optimization
Don't try to remove the containing directory for every pruned object but
try only once after the directory has been scanned instead.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 22:17:47 -07:00
5721685699 improve checkout message when asking for same branch
Change the feedback message if doing 'git checkout foo' when already on
branch "foo".

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 22:17:44 -07:00
ac54c277f0 Be more careful about zlib return values
When creating a new object, we use "deflate(stream, Z_FINISH)" in a loop
until it no longer returns Z_OK, and then we do "deflateEnd()" to finish
up business.

That should all work, but the fact is, it's not how you're _supposed_ to
use the zlib return values properly:

 - deflate() should never return Z_OK in the first place, except if we
   need to increase the output buffer size (which we're not doing, and
   should never need to do, since we pre-allocated a buffer that is
   supposed to be able to hold the output in full). So the "while()" loop
   was incorrect: Z_OK doesn't actually mean "ok, continue", it means "ok,
   allocate more memory for me and continue"!

 - if we got an error return, we would consider it to be end-of-stream,
   but it could be some internal zlib error.  In short, we should check
   for Z_STREAM_END explicitly, since that's the only valid return value
   anyway for the Z_FINISH case.

 - we never checked deflateEnd() return codes at all.

Now, admittedly, none of these issues should ever happen, unless there is
some internal bug in zlib. So this patch should make zero difference, but
it seems to be the right thing to do.

We should probablybe anal and check the return value of "deflateInit()"
too!

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 22:17:32 -07:00
acdeec62cb Don't ever return corrupt objects from "parse_object()"
Looking at the SHA1 validation code due to the corruption that Alexander
Litvinov is seeing under Cygwin, I notice that one of the most central
places where we read objects, we actually do end up verifying the SHA1 of
the result, but then we happily parse it anyway.

And using "printf" to write the error message means that it not only can
get lost, but will actually mess up stdout, and cause other strange and
hard-to-debug failures downstream.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 22:17:17 -07:00
9096c660a8 index-pack: more validation checks and cleanups
When appending objects to a pack, make sure the appended data is really
what we expect instead of simply loading potentially corrupted objects
and legitimating them by computing a SHA1 of that corrupt data.

With this the sha1_object() can lose its test_for_collision parameter
which is now redundent.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 22:09:59 -07:00
ce9fbf16e0 index-pack: use hash_sha1_file()
Use hash_sha1_file() instead of duplicating code to compute object SHA1.
While at it make it accept a const pointer.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 22:09:57 -07:00
8685da4256 don't ever allow SHA1 collisions to exist by fetching a pack
Waaaaaaay back Git was considered to be secure as it never overwrote
an object it already had.  This was ensured by always unpacking the
packfile received over the network (both in fetch and receive-pack)
and our already existing logic to not create a loose object for an
object we already have.

Lately however we keep "large-ish" packfiles on both fetch and push
by running them through index-pack instead of unpack-objects.  This
would let an attacker perform a birthday attack.

How?  Assume the attacker knows a SHA-1 that has two different
data streams.  He knows the client is likely to have the "good"
one.  So he sends the "evil" variant to the other end as part of
a "large-ish" packfile.  The recipient keeps that packfile, and
indexes it.  Now since this is a birthday attack there is a SHA-1
collision; two objects exist in the repository with the same SHA-1.
They have *very* different data streams.  One of them is "evil".

Currently the poor recipient cannot tell the two objects apart,
short of by examining the timestamp of the packfiles.  But lets
say the recipient repacks before he realizes he's been attacked.
We may wind up packing the "evil" version of the object, and deleting
the "good" one.  This is made *even more likely* by Junio's recent
rearrange_packed_git patch (b867092f).

It is extremely unlikely for a SHA1 collisions to occur, but if it
ever happens with a remote (hence untrusted) object we simply must
not let the fetch succeed.

Normally received packs should not contain objects we already have.
But when they do we must ensure duplicated objects with the same SHA1
actually contain the same data.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 22:08:25 -07:00
8bf0e3d15d Teach git-remote to list pushed branches.
The configured refspecs are printed almost verbatim, i.e. both the local
and the remote branch name separated by a colon are printed; only the
prefix 'refs/heads/' is removed, like this:

  Local branch(es) pushed with 'git push'
    master refs/tags/*:refs/tags/* next:next

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 01:54:49 -07:00
08727ea8bb git-fetch: Fix single_force in append_fetch_head
This fixes the single force (+) when fetched with fetch_per_ref.

Also use $LF as separator because IFS is $LF.

Signed-off-by: Santi Béjar <sbejar@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-20 01:52:11 -07:00
bb95e19c5f Merge git://git2.kernel.org/pub/scm/gitk/gitk
* git://git2.kernel.org/pub/scm/gitk/gitk:
  [PATCH] gitk: bind <F5> key to Update (reread commits)
2007-03-19 23:47:22 -07:00
7e8c8255e9 make git clone -q suppress the noise with http fetch
We already have -q in git clone.  So for those who care to suppress
the noise during an http based clone, make -q actually do a quiet
http fetch.

Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Cc: Fernando Herrera <fherrera@onirica.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 23:46:30 -07:00
456cdf6edb Fix loose object uncompression check.
The thing is, if the output buffer is empty, we should *still* actually
use the zlib routines to *unpack* that empty output buffer.

But we had a test that said "only unpack if we still expect more output".

So we wouldn't use up all the zlib stream, because we felt that we didn't
need it, because we already had all the bytes we wanted. And it was
"true": we did have all the output data. We just needed to also eat all
the input data!

We've had this bug before - thinking that we don't need to inflate()
anything because we already had it all..

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 23:13:17 -07:00
3e993bb657 contrib/continuous: a continuous integration build manager
This is a simple but powerful continuous integration build system
for Git.  It works by receiving push events from repositories
through the post-receive hook, aggregates them on a per-branch
basis into a first-come-first-serve build queue, and lets a
background build daemon perform builds one at a time.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 22:21:19 -07:00
1b89ef1731 Provide some technical documentation for shallow clones
There has not been any work on the shallow stuff lately, so it is hard
to find out what it does, and how. This document describes the ideas
as well as the current problems, and can serve as a starting point for
shallow people.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 22:19:29 -07:00
e29b96d5aa Add a HOWTO for setting up a standalone git daemon
Setting up a git-daemon came up the other day on IRC, and it is slightly
non trivial for the uninitiated.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 22:17:38 -07:00
824f782c3f xdiff/xutils.c(xdl_hash_record): factor out whitespace handling
Since in at least one use case, xdl_hash_record() takes over 15% of the
CPU time, it makes sense to even micro-optimize it. For many cases, no
whitespace special handling is needed, and in these cases we should not
even bother to check for whitespace in _every_ iteration of the loop.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 22:17:25 -07:00
57584d9edd blame: micro-optimize cmp_suspect()
The commit structures are guaranteed their uniqueness by the object
layer, so we can check their address and see if they are the same
without going down to the object sha1 level.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 22:17:10 -07:00
567fb65e25 Replace remaining instances of strdup with xstrdup.
Signed-off-by: James Bowes <jbowes@dangerouslyinc.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 18:16:03 -07:00
5e08ecbff2 use a LRU eviction policy for the delta base cache
This provides a smoother degradation in performance when the cache
gets trashed due to the delta_base_cache_limit being reached.  Limited
testing with really small delta_base_cache_limit values appears to confirm
this.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 18:16:02 -07:00
3358004a00 clean up the delta base cache size a bit
Currently there are 3 different ways to deal with the cache size.
Let's stick to only one.  The compiler is smart enough to produce the exact
same code in those cases anyway.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 18:15:59 -07:00
ceb8442af7 GIT 1.5.1-rc1
I think we can start to slow down, as we now have covered
everything I listed earlier in the short-term release plan.

The last release 1.5.0 took painfully too long.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 02:56:29 -07:00
843d49a479 Fix merge-index
An earlier conversion to run_command() from execlp() forgot that
run_command() takes an array that is terminated with NULL.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 02:48:37 -07:00
5d86501742 Set up for better tree diff optimizations
This is mainly just a cleanup patch, and sets up for later changes where
the tree-diff.c "interesting()" function can return more than just a
yes/no value.

In particular, it should be quite possible to say "no subsequent entries
in this tree can possibly be interesting any more", and thus allow the
callers to short-circuit the tree entirely.

In fact, changing the callers to do so is trivial, and is really all this
patch really does, because changing "interesting()" itself to say that
nothing further is going to be interesting is definitely more complicated,
considering that we may have arbitrary pathspecs.

But in cleaning up the callers, this actually fixes a potential small
performance issue in diff_tree(): if the second tree has a lot of
uninterestign crud in it, we would keep on doing the "is it interesting?"
check on the first tree for each uninteresting entry in the second one.

The answer is obviously not going to change, so that was just not helping.
The new code is clearer and simpler and avoids this issue entirely.

I also renamed "interesting()" to "tree_entry_interesting()", because I
got frustrated by the fact that

 - we actually had *another* function called "interesting()" in another
   file, and I couldn't tell from the profiles which one was the one that
   mattered more.

 - when rewriting it to return a ternary value, you can't just do

	if (interesting(...))
		...

   any more, but want to assign the return value to a local variable. The
   name of choice for that variable would normally be "interesting", so
   I just wanted to make the function name be more specific, and avoid
   that whole issue (even though I then didn't choose that name for either
   of the users, just to avoid confusion in the patch itself ;)

In other words, this doesn't really change anything, but I think it's a
good thing to do, and if somebody comes along and writes the logic for
"yeah, none of the pathspecs you have are interesting", we now support
that trivially.

It could easily be a meaningful optimization for things like "blame",
where there's just one pathspec, and stopping when you've seen it would
allow you to avoid about 50% of the tree traversals on average.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 02:01:39 -07:00
c711a214c1 Trivial cleanup of track_tree_refs()
This makes "track_tree_refs()" use the same "tree_entry()" function for
counting the entries as it does for actually traversing them a few lines
later.

Not a biggie, but the reason I care was that this was the only user of
"update_tree_entry()" that didn't actually *extract* the tree entry first.
It doesn't matter as things stand now, but it meant that a separate
test-patch I had that avoided a few more "strlen()" calls by just saving
the entry length in the entry descriptor and using it directly when
updating wouldn't work without this patch.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 01:48:56 -07:00
d55552f6e3 git.el: Add support for commit hooks.
Run the pre-commit and post-commit hooks at appropriate places, and
display their output if any.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-19 01:40:27 -07:00
94b9816c5c Merge branch 'jb/gc'
* jb/gc:
  Make gc a builtin.
2007-03-18 22:46:30 -07:00
de5e61eb0d Merge branch 'fl/cvsserver'
* fl/cvsserver:
  cvsserver: further improve messages on commit and status
  cvsserver: Be more chatty
2007-03-18 22:44:25 -07:00
18bdec1118 Limit the size of the new delta_base_cache
The new configuration variable core.deltaBaseCacheLimit allows the
user to control how much memory they are willing to give to Git for
caching base objects of deltas.  This is not normally meant to be
a user tweakable knob; the "out of the box" settings are meant to
be suitable for almost all workloads.

We default to 16 MiB under the assumption that the cache is not
meant to consume all of the user's available memory, and that the
cache's main purpose was to cache trees, for faster path limiters
during revision traversal.  Since trees tend to be relatively small
objects, this relatively small limit should still allow a large
number of objects.

On the other hand we don't want the cache to start storing 200
different versions of a 200 MiB blob, as this could easily blow
the entire address space of a 32 bit process.

We evict OBJ_BLOB from the cache first (credit goes to Junio) as
we want to favor OBJ_TREE within the cache.  These are the objects
that have the highest inflate() startup penalty, as they tend to
be small and thus don't have that much of a chance to ammortize
that penalty over the entire data.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-18 22:43:37 -07:00
3635a18770 Merge branch 'sp/run-command'
* sp/run-command:
  Use run_command within send-pack
  Use run_command within receive-pack to invoke index-pack
  Use run_command within merge-index
  Use run_command for proxy connections
  Use RUN_GIT_CMD to run push backends
  Correct new compiler warnings in builtin-revert
  Replace fork_with_pipe in bundle with run_command
  Teach run-command to redirect stdout to /dev/null
  Teach run-command about stdout redirection
2007-03-18 22:21:06 -07:00
abec100c33 Make git-send-email aware of Cc: lines.
In the Linux kernel, for example, it's common to include Cc: lines
for cases when you want to remember to cc someone on a patch without
necessarily claiming they signed off on it.  Make git-send-email
aware of these.

Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-18 21:10:03 -07:00
d6678c28e3 mergetool: print an appropriate warning if merge.tool is unknown
Also add support for vimdiff

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2007-03-18 22:30:10 -04:00
9cec65399d mergetool: Add support for vimdiff.
Signed-off-by: James Bowes <jbowes@dangerouslyinc.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2007-03-18 22:13:48 -04:00
7976ce1b90 Update main git.html page to point at 1.5.0.5 documentation
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-18 15:58:07 -07:00
d54fe394ac Merge branch 'ar/diff'
* ar/diff:
  Add tests for --quiet option of diff programs
  try-to-simplify-commit: use diff-tree --quiet machinery.
  revision.c: explain what tree_difference does
  Teach --quiet to diff backends.
  diff --quiet
  Remove unused diffcore_std_no_resolve
  Allow git-diff exit with codes similar to diff(1)
2007-03-18 15:48:06 -07:00
304de2d2d6 Avoid unnecessary strlen() calls
This is a micro-optimization that grew out of the mailing list discussion
about "strlen()" showing up in profiles.

We used to pass regular C strings around to the low-level tree walking
routines, and while this worked fine, it meant that we needed to call
strlen() on strings that the caller always actually knew the size of
anyway.

So pass the length of the string down wih the string, and avoid
unnecessary calls to strlen(). Also, when extracting a pathname from a
tree entry, use "tree_entry_len()" instead of strlen(), since the length
of the pathname is directly calculable from the decoded tree entry itself
without having to actually do another strlen().

This shaves off another ~5-10% from some loads that are very tree
intensive (notably doing commit filtering by a pathspec).

Signed-off-by: Linus Torvalds  <torvalds@linux-foundation.org>"
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-18 15:36:59 -07:00
a0cba10847 Reuse cached data out of delta base cache.
A malloc() + memcpy() will always be faster than mmap() +
malloc() + inflate().  If the data is already there it is
certainly better to copy it straight away.

With this patch below I can do 'git log drivers/scsi/ >
/dev/null' about 7% faster.  I bet it might be even more on
those platforms with bad mmap() support.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-18 15:36:59 -07:00
e5e01619bc Implement a simple delta_base cache
This trivial 256-entry delta_base cache improves performance for some
loads by a factor of 2.5 or so.

Instead of always re-generating the delta bases (possibly over and over
and over again), just cache the last few ones. They often can get re-used.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-18 15:36:59 -07:00
62f255ad58 Make trivial wrapper functions around delta base generation and freeing
This doesn't change any code, it just creates a point for where we'd
actually do the caching of delta bases that have been generated.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-18 15:36:59 -07:00
5bb44a5103 Merge 1.5.0.5 in from 'maint' 2007-03-18 15:36:44 -07:00
6757ada403 Make gc a builtin.
Signed-off-by: James Bowes <jbowes@dangerouslyinc.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-17 00:34:19 -07:00
1589e0517f Merge branch 'maint'
* maint:
  git-merge: finish when git-read-tree fails
2007-03-17 00:33:17 -07:00
4287307833 [PATCH] clean up pack index handling a bit
Especially with the new index format to come, it is more appropriate
to encapsulate more into check_packed_git_idx() and assume less of the
index format in struct packed_git.

To that effect, the index_base is renamed to index_data with void * type
so it is not used directly but other pointers initialized with it. This
allows for a couple pointer cast removal, as well as providing a better
generic name to grep for when adding support for new index versions or
formats.

And index_data is declared const too while at it.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-16 21:27:36 -07:00
ac527b0b7c [PATCH] add test for OFS_DELTA objects
Make sure pack-objects with --delta-base-offset works fine, and that
it actually produces smaller packs as expected.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-16 21:27:36 -07:00
82868f72b5 [PATCH] fix t5300-pack-object.sh
The 'use packed deltified objects' test was flawed as it failed to
remove the pack and index from the previous test, effectively preventing
the desired pack from being exercised as objects could be found in that
other pack instead.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-16 21:27:35 -07:00
e8e91fece8 [PATCH] local-fetch.c: some error printing cleanup
Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-16 21:27:35 -07:00
0d38ab259e applymbox: brown paper bag fix.
An earlier patch 87ab7992 broke applymbox by blindly copying piece
from git-am, causing a harmless but annoying series of error messages.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-16 21:22:05 -07:00
0c66d6be4f Add tests for --quiet option of diff programs
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
2007-03-16 02:13:27 -07:00
dbb2b41aa4 use xstrdup please
We generally prefer xstrdup to just plain strdup.
Make it so.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-16 02:12:14 -07:00
9debc3241b git-fetch, git-branch: Support local --track via a special remote '.'
This patch adds support for a dummy remote '.' to avoid having
to declare a fake remote like

        [remote "local"]
                url = .
                fetch = refs/heads/*:refs/heads/*

Such a builtin remote simplifies the operation of "git-fetch",
which will populate FETCH_HEAD but will not pretend that two
repositories are in use, will not create a thin pack, and will
not perform any useless remapping of names.  The speed
improvement is around 20%, and it should improve more if
"git-fetch" is converted to a builtin.

To this end, git-parse-remote is grown with a new kind of
remote, 'builtin'.  In git-fetch.sh, we treat the builtin remote
specially in that it needs no pack/store operations.  In fact,
doing git-fetch on a builtin remote will simply populate
FETCH_HEAD appropriately.

The patch also improves of the --track/--no-track support,
extending it so that branch.<name>.remote items referring '.'
can be created.  Finally, it fixes a typo in git-checkout.sh.

Signed-off-by: Paolo Bonzini  <bonzini@gnu.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-16 02:10:12 -07:00
0053e902b4 git-log --first-parent: show only the first parent log
If your development history does not have fast-forward merges,
i.e. the "first parent" of commits in your history are special
than other parents, this option gives a better overview of the
evolution of a particular branch.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 16:22:18 -07:00
dd47aa3133 try-to-simplify-commit: use diff-tree --quiet machinery.
This uses diff-tree --quiet machinery to terminate the internal
diff-tree between a commit and its parents via revs.pruning (not
revs.diffopt) as soon as we find enough about the tree change.

With respect to the optionally given pathspec, we are interested
if the tree of commit is identical to the parent's, only adds
new paths to the parent's, or there are other differences.  As
soon as we find out that there is one such other kind of
difference, we do not have to compare the rest of the tree.

Because we do not call standard diff_addremove/diff_change, we
instruct the diff-tree machinery to stop early by setting
has_changes when we say we found the trees to be different.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 16:21:19 -07:00
0a4ba7f8c6 revision.c: explain what tree_difference does
This explains how tree_difference variable is used, and updates two
places where the code knows symbolic constant REV_TREE_SAME is 0.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 16:21:19 -07:00
822cac0155 Teach --quiet to diff backends.
This teaches git-diff-files, git-diff-index and git-diff-tree
backends to exit early under --quiet option.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 16:21:19 -07:00
68aacb2f3c diff --quiet
This adds the command line option 'quiet' to tell 'git diff-*'
that we are not interested in the actual diff contents but only
want to know if there is any change.  This option automatically
turns --exit-code on, and turns off output formatting, as it
does not make much sense to show the first hit we happened to
have found.

The --quiet option is silently turned off (but --exit-code is
still in effect, so is silent output) if postprocessing filters
such as pickaxe and diff-filter are used.  For all practical
purposes I do not think of a reason to want to use these filters
and not viewing the diff output.

The backends have not been taught about the option with this patch.
That is a topic for later rounds.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 16:21:19 -07:00
3161b4b521 Remove unused diffcore_std_no_resolve
This was only used by diff-tree-helper program, whose purpose
was to translate a raw diff to a patch.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 16:21:19 -07:00
41bbf9d585 Allow git-diff exit with codes similar to diff(1)
This introduces a new command-line option: --exit-code. The diff
programs will return 1 for differences, return 0 for equality, and
something else for errors.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 16:21:19 -07:00
803527f1d9 Merge GIT 1.5.0.4 2007-03-14 15:59:04 -07:00
c47e6a43d3 update-hook: fix incorrect use of git-describe and sed for finding previous tag
Previously git-describe would output lines of the form
 v1.1.1-gf509d56
The update hook found the dash and stripped it off using
 sed 's/-g.*//'
The remainder was then used as the previous tag name.

However, git-describe has changed format.  The output is now of the form
 v1.1.1-23-gf509d56
The above sed fragment doesn't strip the middle "-23", and so the
previous tag name used would be "v1.1.1-23".  This is incorrect.

Since the hook script was written, git-describe now gained support for
"--abbrev=0", which it uses as a special flag to tell it not to output
anything other than the nearest tag name.  This patch fixes the problem,
and prevents any future recurrence by using this new flag rather than
sed to find the previous tag.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 09:14:51 -07:00
392e28170b cvsserver: further improve messages on commit and status
commit: Also print the old revision similar to how cvs does it and
prepend a line stating the filename so that one can actually
understand what happened when commiting more than one file.

status: Fix the RCS filename displayed. The directory was
printed twice.

Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 02:09:33 -07:00
459bad77e7 cvsserver: Be more chatty
Submit some additional messages to the client on commit and update.
Inspired by the standard CVS server though a little more terse.

Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 02:09:32 -07:00
c49b260e99 Merge branch 'jc/repack'
* jc/repack:
  prepare_packed_git(): sort packs by age and localness.
2007-03-14 02:08:48 -07:00
c1f5086e23 Merge branch 'jc/fetch'
* jc/fetch:
  .gitignore: add git-fetch--tool
  builtin-fetch--tool: fix reflog notes.
  git-fetch: retire update-local-ref which is not used anymore.
  builtin-fetch--tool: make sure not to overstep ls-remote-result buffer.
  fetch--tool: fix uninitialized buffer when reading from stdin
  builtin-fetch--tool: adjust to updated sha1_object_info().
  git-fetch--tool takes flags before the subcommand.
  Use stdin reflist passing in git-fetch.sh
  Use stdin reflist passing in parse-remote
  Allow fetch--tool to read from stdin
  git-fetch: rewrite expand_ref_wildcard in C
  git-fetch: rewrite another shell loop in C
  git-fetch: move more code into C.
  git-fetch--tool: start rewriting parts of git-fetch in C.
  git-fetch: split fetch_main into fetch_dumb and fetch_native
2007-03-14 01:40:19 -07:00
5a27b3211a Merge branch 'dz/mailinfo'
* dz/mailinfo:
  Add a couple more test cases to the suite.
  restrict the patch filtering
  builtin-mailinfo.c infrastrcture changes
2007-03-14 01:39:19 -07:00
c746e44fb8 Merge branch 'jb/per-user-exclude'
* jb/per-user-exclude:
  add: Support specifying an excludes file with a configuration variable
2007-03-14 01:38:57 -07:00
c379c4b176 Merge branch 'maint'
* maint:
  cvsserver: asciidoc formatting changes
2007-03-14 01:38:39 -07:00
36db2399e0 Merge branch 'pb/branch-track'
* pb/branch-track:
  Fix broken create_branch() in builtin-branch.
  git-branch, git-checkout: autosetup for remote branch tracking
2007-03-14 01:38:28 -07:00
09f2825147 git-grep: don't use sscanf
If you use scanf or sscanf to parse integers, your code probably
accepts bogus inputs.  For example, builtin-grep (aka git-grep) uses
sscanf(scan, "%u", &num) to parse the integer argument to -A, -B, -C.
Currently, "-C 1,000" and "-C 4294967297" are both treated just like
"-C 1":

    $ git-grep -h -C 4294967297 juggle
    out and you may find it easier to switch back and forth if you
    juggle multiple lines of development simultaneously. Of
    course, you will pay the price of more disk usage to hold

The obvious fix is to use strtoul instead.  But using a bare strtoul is
too messy, at least when done properly, so I've added a wrapper function.

The new function in the patch below belongs elsewhere if it would be
useful in replacing any of the four remaining uses of sscanf.

One final note:  With this change, I get a slightly different
diagnostic depending on the context size:

  $ ./git-grep -h -C 4294967296 juggle
  fatal: 4294967296: invalid context length argument
  [Exit 128]
  $ ./git-grep -h -C 4294967295 juggle
  grep: 4294967295: invalid context length argument

  [Exit 1]

A common convention that makes it easy to identify the source
of a diagnostic is to include the program name before the first ":".
Whether that should be "git" or "git-grep" is another question.
Using "grep" or "fatal" is misleading.

Signed-off-by: Jim Meyering <jim@meyering.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 01:37:50 -07:00
6cd7895fee Do not output "GEN " when generating perl.mak
This fixes the same issue as 8bef6204, which became an issue again
after 31d0399c.

Besides, it is not really helpful to print just "GEN " (_without_
"perl.mak").

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 01:33:49 -07:00
0497c620ca shortlog: prompt when reading from terminal by mistake
I was trying to see who have been active recently to find GSoC
mentor candidates by running:

	$ git shortlog -s -n --since=4.months | head -n 20

After waiting for about 20 seconds, I started getting worried,
thinking that the recent revision traversal updates might have
had an unintended side effect.

Not so.  "git shortlog" acts as a filter when no revs are given,
unlike "git log" which defaults to HEAD.  It was reading from
its standard input.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 01:33:41 -07:00
86952cdabd Documentation: add git-mergetool to the command list.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-14 01:29:26 -07:00
4739cea566 Merge branch 'master' of git://repo.or.cz/git/mergetool
* 'master' of git://repo.or.cz/git/mergetool:
  Add git-mergetool to run an appropriate merge conflict resolution program
2007-03-14 01:13:39 -07:00
dee41f3e55 git-svn: add -l/--local command to "git svn rebase"
This avoids fetching new revisions remotely, and is usefuly
versus plain "git rebase" because the user does not have to
specify which remote head to rebase against.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-13 21:18:37 -07:00
c4b4a5af16 Add git-mergetool to run an appropriate merge conflict resolution program
The git-mergetool program can be used to automatically run an appropriate
merge resolution program to resolve merge conflicts.  It will automatically
run one of kdiff3, tkdiff, meld, xxdiff, or emacs emerge programs.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2007-03-13 20:14:05 -04:00
38b1c6626b Use run_command within send-pack
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:18 -07:00
e8016abf8d Use run_command within receive-pack to invoke index-pack
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:18 -07:00
b49809c961 Use run_command within merge-index
Maybe unnecessary as the merge-index utility may go away in the
future, but its currently here, its shorter to use run_command,
and probably will help the MinGW port out.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:18 -07:00
15a1c01263 Use run_command for proxy connections
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:18 -07:00
df91ba36b1 Use RUN_GIT_CMD to run push backends
If we hand run_command RUN_GIT_CMD rather than 0 it will use
the execv_git_cmd path rather than execvp at the OS level.
This is typically the preferred way of running another Git
utility.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:18 -07:00
1a8f27413b Correct new compiler warnings in builtin-revert
The new builtin-revert code introduces a few new compiler errors
when I'm building with my stricter set of checks enabled in CFLAGS.
These all just stem from trying to store a constant string into
a non-const char*.  Simple fix, make the variables const char*.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:18 -07:00
b1daf300d0 Replace fork_with_pipe in bundle with run_command
Now that the run_command family supports all of the redirection
modes needed by builtin-bundle, we can use those functions rather
than the underlying POSIX primitives.  This should help to make the
bundle command slightly more portable to other systems, like Windows.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:17 -07:00
e4507ae84e Teach run-command to redirect stdout to /dev/null
Some run-command callers may wish to just discard any data that
is sent to stdout from the child.  This is a lot like our existing
no_stdin support, we just open /dev/null and duplicate the descriptor
into position.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:17 -07:00
f4bba25bdc Teach run-command about stdout redirection
Some potential callers of the run_command family of functions need
to control not only the stdin redirection of the child, but also
the stdout redirection of the child.  This can now be setup much
like the already existing stdin redirection.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:40:17 -07:00
ae1a743735 Add a couple more test cases to the suite.
They handle cases where there is no attached patch.

Signed-off-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:33:41 -07:00
f0658cf210 restrict the patch filtering
I have come across many emails that use long strings of '-'s as separators
for ideas.  This patch below limits the separator to only 3 '-', with the
intent that long string of '-'s will stay in the commit msg and not in the
patch file.

Signed-off-by: Don Zickus <dzickus@redhat.com>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:33:41 -07:00
87ab799234 builtin-mailinfo.c infrastrcture changes
I am working on a project that required parsing through regular
mboxes that didn't necessarily have patches embedded in them.  I
started by creating my own modified copy of git-am and working
from there.  Very quickly, I noticed git-mailinfo wasn't able to
handle a big chunk of my email.

After hacking up numerous solutions and running into more
limitations, I decided it was just easier to rewrite a big chunk
of it.  The following patch has a bunch of fixes and features
that I needed in order for me do what I wanted.

Note: I'm didn't follow any email rfc papers but I don't think
any of the changes I did required much knowledge (besides the
boundary stuff).

List of major changes/fixes:
- can't create empty patch files fix
- empty patch files don't fail, this failure will come inside git-am
- multipart boundaries are now handled
- only output inbody headers if a patch exists otherwise assume those
headers are part of the reply and instead output the original headers
- decode and filter base64 patches correctly
- various other accidental fixes

I believe I didn't break any existing functionality or
compatibility (other than what I describe above, which is really
only the empty patch file).

I tested this through various mailing list archives and
everything seemed to parse correctly (a couple thousand emails).

[jc: squashed in another patch from Don's five patch series to
 fix the test case, as this patch exposes the bug in the test.]

Signed-off-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 23:33:41 -07:00
27ebd6e044 Merge branch 'master' of git://repo.or.cz/git-gui
* 'master' of git://repo.or.cz/git-gui:
  git-gui: Support of "make -s" in: do not output anything of the build itself
2007-03-12 23:14:07 -07:00
9550a9cea9 Merge branch 'maint'
* maint:
  Don't package the git-gui credits file anymore
  git-gui: Allow 'git gui version' outside of a repository
  git-gui: Revert "git-gui: Display all authors of git-gui."
  git-gui: Revert "Don't modify CREDITS-FILE if it hasn't changed."
  git-gui: Allow committing empty merges
2007-03-12 23:13:01 -07:00
f8a066581d Merge branch 'master' of git://repo.or.cz/git/fastimport
* 'master' of git://repo.or.cz/git/fastimport:
  Remove unnecessary casts from fast-import
  New fast-import test case for valid tree sorting
  fast-import: grow tree storage more aggressively
2007-03-12 23:10:23 -07:00
6016e35bc1 Fix t5510-fetch's use of sed
POSIX says sed may add a trailing LF if there isn't already
one there.  We shouldn't rely on it not adding that LF, as
some systems (Mac OS X for example) will add it.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 17:37:30 -07:00
9dc09c7664 Simplify closing two fds at once in run-command.c
I started hacking on a change to add stdout redirection support to
the run_command family, but found I was using a lot of close calls
on two pipes in an array (such as for pipe).  So I'm doing a tiny
bit of refactoring first to make the next set of changes clearer.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 16:31:35 -07:00
061e35c581 Remove unnecessary casts from fast-import
Jeff King pointed out that these casts are quite unnecessary, as
the compiler should be doing them anyway, and may cause problems
in the future if the size of the argument for to_atom were to ever
be increased.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-03-12 15:48:37 -04:00
7f09ac4714 Merge branch 'maint'
* maint:
  fast-import: grow tree storage more aggressively
2007-03-12 15:04:46 -04:00
e741130386 New fast-import test case for valid tree sorting
The Git tree sorting convention is more complex than just the name,
it needs to include the mode too to make sure trees sort as though
their name ends with "/".

This is a simple test case that verifies fast-import keeps the tree
ordering correct after editing the same tree twice in a single
input stream.  A recent proposed patch series (that has not yet
been applied) will cause this test to fail, due to a bug in the
way the series handles sorting within the trees.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-03-12 15:02:13 -04:00
1358e7d670 Re-fix get_sha1_oneline()
What the function wants to return is not if we saw any return
from pop_most_recent_commit(), but if we found what was asked
for.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-12 11:30:38 -07:00
2ec0cb7959 Merge branch 'maint'
* maint:
  git-gui: Allow 'git gui version' outside of a repository
  git-gui: Revert "git-gui: Display all authors of git-gui."
  git-gui: Revert "Don't modify CREDITS-FILE if it hasn't changed."
  git-gui: Allow committing empty merges
2007-03-12 13:26:59 -04:00
e7a0919115 [PATCH] gitk: bind <F5> key to Update (reread commits)
I chose <F5> because it's also the key to reload the current
page in web browsers such as Konqueror and Firefox, so users
are more likely to be familiar with it.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>
2007-03-12 20:13:02 +11:00
34572ed2c8 git-bundle: only die if pack would be empty, warn if ref is skipped
A use case for git-bundle expected to be quite common is this:

	$ git bundle create daily.bundle --since=10.days.ago --all

The expected outcome is _not_ to error out if only a couple of the
refs were not changed during the last 10 days.

This patch complains loudly about refs which are skipped due to the
pack not containing the corresponding objects, but dies only if
no objects would be in the pack _at all_.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 23:55:46 -07:00
4a62d3f5b2 git-send-email: configurable bcc and chain-reply-to
Chain-reply-to is a personal perference, and is unlikely to change from
patchset to patchset.  Similarly, bcc is likely to have the same values
every invocation is one likes to bcc oneself.

So, allow both to be set via configuration variables.

Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 23:53:57 -07:00
240c77c714 Merge branch 'maint'
* maint:
  git-send-email: Document configuration options
  git-merge: warn when -m provided on a fast forward
2007-03-11 23:53:52 -07:00
2422f1ca3b Merge branch 'jc/boundary'
* jc/boundary:
  git-bundle: prevent overwriting existing bundles
  git-bundle: die if a given ref is not included in bundle
  git-bundle: handle thin packs in subcommand "unbundle"
  git-bundle: Make thin packs
  git-bundle: avoid packing objects which are in the prerequisites
  bundle: fix wrong check of read_header()'s return value & add tests
  revision --boundary: fix uncounted case.
  revision --boundary: fix stupid typo
  git-bundle: make verify a bit more chatty.
  revision traversal: SHOWN means shown
  git-bundle: various fixups
  revision traversal: retire BOUNDARY_SHOW
  revision walker: Fix --boundary when limited
2007-03-11 23:02:52 -07:00
f43cd49fb8 Change {pre,post}-receive hooks to use stdin
Sergey Vlasov, Andy Parkins and Alex Riesen all pointed out that it
is possible for a single invocation of receive-pack to be given more
refs than the OS might allow us to pass as command line parameters
to a single hook invocation.

We don't want to break these up into multiple invocations (like
xargs might do) as that makes it impossible for the pre-receive
hook to verify multiple related ref updates occur at the same time,
and it makes it harder for post-receive to send out a single batch
notification.

Instead we pass the reference data on a pipe connected to the
hook's stdin, supplying one ref per line to the hook.  This way a
single hook invocation can obtain an infinite amount of ref data,
without bumping into any operating system limits.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:56:03 -07:00
1d9e8b56fe Split back out update_hook handling in receive-pack
Since we have decided to change the calling conventions for the
pre-receive and post-receive hooks to take the ref data on stdin
rather than on the command line we cannot use the same logic to
invoke the update hook anymore.

So we take a small step backwards towards what we used to have,
and create a specialized function for executing just the update
hook.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:46 -07:00
6c319a22e4 Refactor run_command error handling in receive-pack
I'm pulling the error handling used to decode the result of
run_command up into a new function so that I can reuse it.
No changes, just a simple code movement.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:43 -07:00
4919bf0354 Teach run_command how to setup a stdin pipe
Sometimes callers trying to use run_command to execute a child
process will want to setup a pipe or file descriptor to redirect
into the child's stdin.

This idea is completely stolen from builtin-bundle's fork_with_pipe,
written by Johannes Schindelin.  All credit (and blame) should lie
with Dscho.  ;-)

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:40 -07:00
ebcb5d16ca Split run_command into two halves (start/finish)
If the calling process wants to send data to stdin of a
child process it will need to arrange for a pipe and get
the child process running, feed data to it, then wait
for the child process to finish.  So we split the run
function into two halves, allowing callers to first
start the child then later finish it.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:37 -07:00
f1000898d4 Start defining a more sophisticated run_command
There are a number of places where we do some variation of
fork()+exec() but we also need to setup redirection in the process,
much like what run_command does for us already with its option flags.

It would be nice to reuse more of the run_command logic, especially
as that non-fork API helps us to port to odd platforms like Win32.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:34 -07:00
afdb269c76 Remove unused run_command variants
We don't actually use these va_list based variants of run_command
anymore.  I'm removing them before I make further improvements.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:31 -07:00
497bdc88d6 Switch to run_command_v_opt in revert
Another change by me is removing the va_list variants of run_command,
one of which is used by builtin-revert.c.  To avoid compile errors
I'm refactoring builtin-revert to use the char** variant instead,
as that variant is staying.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:25 -07:00
538778469c cvsserver: Use Merged response instead of Update-existing for merged files
Using Update-existing leads to the client forgetting about the "locally
modified" status of the file which can lead to loss of local changes on
later updates.

Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de>
Acked-by: Martin Langhoff <martin.langhoff@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 22:49:08 -07:00
ed8ad7e2e2 I like the idea of the new ':/<oneline prefix>' notation, and gave it
a try, but all I could get was a segfault.  It was dereferencing a NULL
commit list.  Fix below.  With it, this example now works:

    $ mkdir .j; cd .j; touch f
    $ git-init; git-add f; git-commit -mc f; echo x >f; git-commit -md f
    $ git-diff -p :/c :/d
    diff --git a/f b/f
    index e69de29..587be6b 100644
    --- a/f
    +++ b/f
    @@ -0,0 +1 @@
    +x

Signed-off-by: Jim Meyering <jim@meyering.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 13:28:13 -07:00
b867092fec prepare_packed_git(): sort packs by age and localness.
When accessing objects, we first look for them in packs that
are linked together in the reverse order of discovery.

Since younger packs tend to contain more recent objects, which
are more likely to be accessed often, and local packs tend to
contain objects more relevant to our specific projects, sort the
list of packs before starting to access them.  In addition,
favoring local packs over the ones borrowed from alternates can
be a win when alternates are mounted on network file systems.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-11 00:04:05 -08:00
45994a1e33 Fix broken create_branch() in builtin-branch.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-10 23:41:58 -08:00
0746d19a82 git-branch, git-checkout: autosetup for remote branch tracking
In order to track and build on top of a branch 'topic' you track from
your upstream repository, you often would end up doing this sequence:

  git checkout -b mytopic origin/topic
  git config --add branch.mytopic.remote origin
  git config --add branch.mytopic.merge refs/heads/topic

This would first fork your own 'mytopic' branch from the 'topic'
branch you track from the 'origin' repository; then it would set up two
configuration variables so that 'git pull' without parameters does the
right thing while you are on your own 'mytopic' branch.

This commit adds a --track option to git-branch, so that "git
branch --track mytopic origin/topic" performs the latter two actions
when creating your 'mytopic' branch.

If the configuration variable branch.autosetupmerge is set to true, you
do not have to pass the --track option explicitly; further patches in
this series allow setting the variable with a "git remote add" option.
The configuration variable is off by default, and there is a --no-track
option to countermand it even if the variable is set.

Signed-off-by: Paolo Bonzini  <bonzini@gnu.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-10 23:41:58 -08:00
8a3fbdd9e6 Merge branch 'js/attach'
* js/attach:
  format-patch --attach: not folding some long headers.
  format-patch: add --inline option and make --attach a true attachment
2007-03-10 23:38:18 -08:00
cf6981d493 Merge branch 'js/diff-ni'
* js/diff-ni:
  Get rid of the dependency to GNU diff in the tests
  diff --no-index: support /dev/null as filename
  diff-ni: fix the diff with standard input
  diff: support reading a file from stdin via "-"
2007-03-10 23:26:33 -08:00
8509fed75d Merge branch 'jc/fsck'
* jc/fsck:
  fsck: exit with non-zero status upon errors
  unpack_sha1_file(): detect corrupt loose object files.
  fsck: fix broken loose object check.
2007-03-10 23:10:26 -08:00
ce4474b65d Merge branch 'pb/commit-i'
* pb/commit-i:
  git-commit: add a --interactive option
2007-03-10 23:00:38 -08:00
e286114d0e Merge branch 'js/revert-cherry'
* js/revert-cherry:
  cherry-pick: Bug fix 'cherry picked from' message.
  cherry-pick: Suggest a better method to retain authorship
  Make git-revert & git-cherry-pick a builtin
2007-03-10 23:00:11 -08:00
5339fb2e8b Merge branch 'sp/make'
* sp/make:
  Allow "make -w" generate its usual output
  Support of "make -s": do not output anything of the build itself
  More build output cleaning up
  Make 'make' quiet by default
  Make 'make' quieter while building git
2007-03-10 22:33:13 -08:00
ed287ab7fa Merge branch 'maint'
* maint:
  git.el: Retrieve commit log information from .dotest directory.
  git.el: Avoid appending a signoff line that is already present.
  setup_git_directory_gently: fix off-by-one error
  user-manual: install user manual stylesheet with other web documents
  user-manual: fix rendering of history diagrams
  user-manual: fix missing colon in git-show example
  user-manual: fix inconsistent use of pull and merge
  user-manual: fix inconsistent example
  glossary: fix overoptimistic automatic linking of defined terms
  Documentation: s/seperator/separator/
  Adjust reflog filemode in shared repository
2007-03-10 22:07:26 -08:00
896bdfa258 add: Support specifying an excludes file with a configuration variable
This adds the 'core.excludesfile' configuration variable. This variable can
hold a path to a file containing patterns of file names to exclude from
git-add, like $GIT_DIR/info/exclude. Patterns in the excludes file are used
in addition to those in info/exclude.

Signed-off-by: James Bowes <jbowes@dangerouslyinc.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-09 00:06:00 -08:00
6cbf07efc5 git-commit: add a --interactive option
The --interactive option behaves like "git commit", except that
"git add --interactive" is executed before committing.  It is
incompatible with -a and -i.

Signed-off-by: Paolo Bonzini  <bonzini@gnu.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-09 00:05:23 -08:00
2e578f9a4f git-bundle: prevent overwriting existing bundles
Not only does it prevent accidentally losing older bundles, but it
also fixes a subtle bug: when writing into an existing bundle,
git-pack-objects would not truncate the bundle. Therefore,
fetching from the bundle would trigger an error in unpack-objects:
"fatal: pack has junk at the end".

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-08 22:59:07 -08:00
d58c6184e3 git-bundle: die if a given ref is not included in bundle
The earlier patch tried to be nice by just warning, but it seems
more likely that the user wants to adjust the parameters.

Also, it prevents a bundle containing _all_ revisions in the case
when the user only gave one ref, but also rev-list options which
excluded the ref.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-08 22:58:03 -08:00
263703fff3 git-bundle: handle thin packs in subcommand "unbundle"
The patch to make the packs in a bundle thin forgot the receiving side.
D'oh.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-08 22:57:51 -08:00
bd1fc628b8 Merge branch 'js/config-rename'
* js/config-rename:
  git-config: document --rename-section, provide --remove-section
2007-03-08 00:53:38 -08:00
f45fa2a073 Merge branch 'master' of git://repo.or.cz/git/fastimport
* 'master' of git://repo.or.cz/git/fastimport:
  Allow fast-import frontends to reload the marks table
  Use atomic updates to the fast-import mark file
  Preallocate memory earlier in fast-import
2007-03-07 23:10:05 -08:00
9e64d109f9 git-bundle: Make thin packs
Thin packs are way smaller, but they rely on the receiving end to have the
base objects. However, Git's pack protocol also uses thin packs by
default. So make the packs contained in bundles thin, since bundles are
just another transport.

The patch looks a bit bigger than intended, mainly because --thin
_implies_ that pack-objects should run its own rev-list. Therefore, this
patch removes all the stuff we used to roll rev-list ourselves.

This commit also changes behaviour slightly: since we now know early
enough if a specified ref is _not_ contained in the pack, we can avoid
putting that ref into the pack. So, we don't die() here, but warn()
instead, and skip that ref.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 18:02:10 -08:00
18449ab0e9 git-bundle: avoid packing objects which are in the prerequisites
When saying something like "--since=1.day.ago" or "--max-count=5",
git-bundle finds the boundary commits which are recorded as
prerequisites. However, it failed to tell pack-objects _not_ to
pack the objects which are in these.

Fix that. And add a test for that.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 17:38:48 -08:00
e8438420bb Allow fast-import frontends to reload the marks table
I'm giving fast-import a lesson on how to reload the marks table
using the same format it outputs with --export-marks.  This way
a frontend can reload the marks table from a prior import, making
incremental imports less painful.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-03-07 18:07:26 -05:00
60b9004cdb Use atomic updates to the fast-import mark file
When we allow fast-import frontends to reload a mark file from a
prior session we want to let them use the same file as they exported
the marks to.  This makes it very simple for the frontend to save
state across incremental imports.

But we don't want to lose the old marks table if anything goes wrong
while writing our current marks table.  So instead of truncating and
overwriting the path specified to --export-marks we use the standard
lockfile code to write the current marks out to a temporary file,
then rename it over the old marks table.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-03-07 18:05:38 -05:00
05ef58ec1f Teach receive-pack to run pre-receive/post-receive hooks
Bill Lear pointed out that it is easy to send out notifications of
changes with the update hook, but successful execution of the update
hook does not necessarily mean that the ref was actually updated.
Lock contention on the ref or being unable to append to the reflog
may prevent the ref from being changed.  Sending out notifications
prior to the ref actually changing is very misleading.

To help this situation I am introducing two new hooks to the
receive-pack flow: pre-receive and post-receive.  These new hooks
are invoked only once per receive-pack execution and are passed
three arguments per ref (refname, old-sha1, new-sha1).

The new post-receive hook is ideal for sending out notifications,
as it has the complete list of all refnames that were successfully
updated as well as the old and new SHA-1 values.  This allows more
interesting notifications to be sent.  Multiple ref updates could
be easily summarized into one email, for example.

The new pre-receive hook is ideal for logging update attempts, as it
is run only once for the entire receive-pack operation.  It can also
be used to verify multiple updates happen at once, e.g. an update
to the `maint` head must also be accompained by a new annotated tag.

Lots of documentation improvements for receive-pack are included
in this change, as we want to make sure the new hooks are clearly
explained.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 15:03:33 -08:00
8aaf7d6410 Refactor handling of error_string in receive-pack
I discovered we did not send an ng line in the report-status feedback
if the ref was not updated because the repository has the config
option receive.denyNonFastForwards enabled.  I think the reason this
happened is that it is simply too easy to forget to set error_string
when returning back a failure from update()

We now return an ng line for a non-fastforward update, which in
turn will cause send-pack to exit with a non-zero exit status.
Hence the modified test.

This refactoring changes update to return a const char* describing
the error, which execute_commands always loads into error_string.
The result is what I think is cleaner code, and allows us to
initialize the error_string member to NULL when we read_head_info.

I want error_string to be NULL in all commands before we call
execute_commands, so that we can reuse the run_hook function to
execute a new pre-receive hook.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 14:47:09 -08:00
c8dd277109 Refactor run_update_hook to be more useful
This is a simple refactoring of run_update_hook to allow the function
to be passed the name of the hook it runs and also to build the
argument list from a list of struct commands, rather than just one
struct command.

The refactoring is to support new pre-receive and post-receive
hooks that will be given the entire list of struct commands,
rather than just one struct command.  These new hooks will follow
in another patch.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 14:45:43 -08:00
3e6e152c74 Don't run post-update hook unless a ref changed
There is little point in executing the post-update hook if all refs
had an error and were unable to be updated.  In this case nothing
new is reachable within the repository, and there is no state change
for the post-update hook to be interested in.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 14:45:42 -08:00
8e663d9e90 Move post-update hook to after all other activity
As the post-update hook is meant to run after we have completed the
receipt of the pushed changes, and it might actually try to kick off
a `repack -a -d`, we should delay on invoking it until after we have
removed the *.keep file on the uploaded pack (if we kept the pack).

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 14:45:40 -08:00
84da035f38 Merge branch 'maint'
* maint:
  Catch write_ref_sha1 failure in receive-pack
  make t8001 work on Mac OS X again
2007-03-07 14:45:25 -08:00
93e72d8d8f Preallocate memory earlier in fast-import
I'm about to teach fast-import how to reload the marks file created
by a prior session.  The general approach that I want to use is to
immediately parse the marks file when the specific argument is found
in argv, thereby allowing the caller to supply multiple marks files,
as the mark space can be sparsely populated.

To make that work out we need to allocate our object tables before
we parse the command line options.  Since none of these tables
depend on the command line options, we can easily relocate them.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-03-07 17:11:02 -05:00
dc49cd769b Cast 64 bit off_t to 32 bit size_t
Some systems have sizeof(off_t) == 8 while sizeof(size_t) == 4.
This implies that we are able to access and work on files whose
maximum length is around 2^63-1 bytes, but we can only malloc or
mmap somewhat less than 2^32-1 bytes of memory.

On such a system an implicit conversion of off_t to size_t can cause
the size_t to wrap, resulting in unexpected and exciting behavior.
Right now we are working around all gcc warnings generated by the
-Wshorten-64-to-32 option by passing the off_t through xsize_t().

In the future we should make xsize_t on such problematic platforms
detect the wrapping and die if such a file is accessed.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 11:15:26 -08:00
6777a59fcd Use off_t in pack-objects/fast-import when we mean an offset
Always use an off_t value in pack-objects anytime we are dealing
with an offset to some data within a packfile.

Also fixed a minor uintmax_t that was incorrectly defined before.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 11:06:33 -08:00
c4001d92be Use off_t when we really mean a file offset.
Not all platforms have declared 'unsigned long' to be a 64 bit value,
but we want to support a 64 bit packfile (or close enough anyway)
in the near future as some projects are getting large enough that
their packed size exceeds 4 GiB.

By using off_t, the POSIX type that is declared to mean an offset
within a file, we support whatever maximum file size the underlying
operating system will handle.  For most modern systems this is up
around 2^60 or higher.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 11:06:25 -08:00
7cadf491c6 Use uint32_t for pack-objects counters.
As we technically try to support up to a maximum of 2**32-1 objects
in a single packfile we should act like it and use unsigned 32 bit
integers for all of our object counts and progress output.

This change does not modify everything in pack-objects that probably
needs to change to fully support the maximum of 2**32-1 objects.
I'm intentionally breaking the improvements into slightly smaller
commits to make them easier to follow.

No logic change should be occuring here, with the exception that
some comparsions will now work properly when the number of objects
exceeds 2**31-1.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 11:02:38 -08:00
326bf39677 Use uint32_t for all packed object counts.
As we permit up to 2^32-1 objects in a single packfile we cannot
use a signed int to represent the object offset within a packfile,
after 2^31-1 objects we will start seeing negative indexes and
error out or compute bad addresses within the mmap'd index.

This is a minor cleanup that does not introduce any significant
logic changes.  It is roach free.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 11:02:33 -08:00
3a55602eec General const correctness fixes
We shouldn't attempt to assign constant strings into char*, as the
string is not writable at runtime.  Likewise we should always be
treating unsigned values as unsigned values, not as signed values.

Most of these are very straightforward.  The only exception is the
(unnecessary) xstrdup/free in builtin-branch.c for the detached
head case.  Since this is a user-level interactive type program
and that particular code path is executed no more than once, I feel
that the extra xstrdup call is well worth the easy elimination of
this warning.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 10:47:10 -08:00
ff1f99453f Don't build external_grep if its not used
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 10:42:07 -08:00
2d88451b7a Fix mmap leak caused by reading bad indexes.
If an index is corrupt, or is simply too new for us to understand,
we were leaking the mmap that held the entire content of the index.
This could be a considerable size on large projects, given that
the index is at least 24 bytes * nr_objects.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 10:41:33 -08:00
30fee0625d Display the null SHA-1 as the base for an OBJ_OFS_DELTA.
Because we are currently cheating and never supplying the delta base
for an OBJ_OFS_DELTA we get a random SHA-1 in the delta base field.
Instead lets clear the hash out so its at least all 0's.  This is
somewhat more obvious that something fishy is going on, like we
don't actually have the SHA-1 of the base handy.  :)

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 10:35:16 -08:00
d9cb5399ee git-archimport: allow remapping branch names
This patch adds support to archimport for remapping the branch
names to match those used in git more closely.  This is useful
for projects that migrate to git (as opposed to users that want
to use git on Arch-based projects).  For example, one can choose
an Arch branch name and call it "master".

The new command-line syntax works even if there is a colon in
a branch name, since only the part after the last colon is taken
to be the git name (git does not allow colons in branch names).

The new feature is implemented so that archives rotated every
year can also be remapped into a single git archive.

Signed-off-by: Paolo Bonzini  <bonzini@gnu.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 10:30:22 -08:00
e3d842cf12 t/t5515-fetch-merge-logic.sh: Add two more tests
They test the behaviour with just a URL in the command line.

Signed-off-by: Santi B,Ai(Bjar <sbejar@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-07 10:22:44 -08:00
8315588b59 bundle: fix wrong check of read_header()'s return value & add tests
If read_header() fails, it returns <0, not 0. Further, an open(/dev/null)
was not checked for errors.

Also, this adds two tests to make sure that the bundle file looks
correct, by checking if it has the header has the expected form, and that
the pack contains the right amount of objects.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 22:06:46 -08:00
edc04e90f5 gitweb: Don't escape attributes in CGI.pm HTML methods
There is no need to escape HTML tag's attributes in CGI.pm
HTML methods (like CGI::a()), because CGI.pm does attribute
escaping automatically.

  $cgi->a({ ... -attribute => atribute_value }, tag_contents)

is translated to

  <a ... attribute="attribute_value">tag_contents</a>

The rules for escaping attribute values (which are string contents) are
different. For example you have to take care about escaping embedded '"'
and "'" characters; CGI::a() does that for us automatically.

CGI::a() does not HTML escape tag_contents; we would need to write

  <a href="URL">some <b>bold</b> text</a>

for example. So we use esc_html (or esc_path) to escape tag_contents
as needed.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 19:04:07 -08:00
a6f37099d0 Allow "make -w" generate its usual output
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 17:17:13 -08:00
b777434383 Support of "make -s": do not output anything of the build itself
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 17:17:07 -08:00
31d0399c3c More build output cleaning up
- print output file name for .c files
- suppress output of the names of subdirectories when make changes into them
- use GEN prefix for makefile generation in perl/

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 17:16:37 -08:00
0c3b4aac8e git-gui: Support of "make -s" in: do not output anything of the build itself
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-03-06 19:08:46 -05:00
8839ac9442 revision --boundary: fix uncounted case.
When the list is truly limited and get_revision_1() returned NULL,
the code incorrectly returned it without switching to boundary emiting
mode.  Silly.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 03:20:55 -08:00
c390ae97be gitweb: Change to use explicitly function call cgi->escapHTML()
Change to use explicitly function call cgi->escapHTML().
This fix the problem on some systems that escapeHTML() is not
functioning, as default CGI is not setting 'escape' parameter.

Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 03:08:06 -08:00
892ae6bf13 revision --boundary: fix stupid typo
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 03:00:18 -08:00
80e25ceece git-bundle: make verify a bit more chatty.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 01:08:34 -08:00
c33d859385 revision traversal: SHOWN means shown
This moves the code to set SHOWN on the commit from get_revision_1()
back to get_revision(), so that the bit means what it originally
meant: this commit has been given back to the caller.

Also it fixes the --reverse breakage Dscho pointed out.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 01:08:34 -08:00
c2dea5a11c git-bundle: various fixups
verify_bundle() returned with an error early only when all
prerequisite commits were missing.  It should error out much
earlier when some are missing.

When the rev-list is limited in ways other than revision range
(e.g. --max-count or --max-age), create_bundle() listed all
positive refs given from the command line as if they are
available, but resulting pack may not have some of them.  Add a
logic to make sure all of them are included, and error out
otherwise.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 01:08:34 -08:00
2b064697a5 revision traversal: retire BOUNDARY_SHOW
This removes the flag internally used by revision traversal to
decide which commits are indeed boundaries and renames it to
CHILD_SHOWN.  builtin-bundle uses the symbol for its
verification, but I think the logic it uses it is wrong.  The
flag is still useful but it is local to the git-bundle, so it is
renamed to PREREQ_MARK.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 01:08:34 -08:00
86ab4906a7 revision walker: Fix --boundary when limited
This cleans up the boundary processing in the commit walker.  It

 - rips out the boundary logic from the commit walker. Placing
   "negative" commits in the revs->commits list was Ok if all we
   cared about "boundary" was the UNINTERESTING limiting case,
   but conceptually it was wrong.

 - makes get_revision_1() function to walk the commits and return
   the results as if there is no funny postprocessing flags such
   as --reverse, --skip nor --max-count.

 - makes get_revision() function the postprocessing phase:

   If reverse is given, wait for get_revision_1() to give
   everything that it would normally give, and then reverse it
   before consuming.

   If skip is given, skip that many before going further.

   If max is given, stop when we gave out that many.

   Now that we are about to return one positive commit, mark
   the parents of that commit to be potential boundaries
   before returning, iff we are doing the boundary processing.

   Return the commit.

 - After get_revision() finishes giving out all the positive
   commits, if we are doing the boundary processing, we look at
   the parents that we marked as potential boundaries earlier,
   see if they are really boundaries, and give them out.

It loses more code than it adds, even when the new gc_boundary()
function, which is purely for early optimization, is counted.

Note that this patch is purely for eyeballing and discussion
only.  It breaks git-bundle's verify logic because the logic
does not use BOUNDARY_SHOW flag for its internal computation
anymore.  After we correct it not to attempt to affect the
boundary processing by setting the BOUNDARY_SHOW flag, we can
remove BOUNDARY_SHOW from revision.h and use that bit assignment
for the new CHILD_SHOWN flag.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 01:08:34 -08:00
2314c94770 Make 'make' quiet by default
Per Junio's suggestion we are setting 'make' to be quiet by default,
with `make V=1` available to force GNU make back to its default
behavior of showing each command it is running.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 00:48:13 -08:00
74f2b2a8d0 Make 'make' quieter while building git
I find it difficult to see compiler warnings amongst the massive
spewing produced by GNU make as it works through our productions.
This is especially true if CFLAGS winds up being rather long, due
to a large number of -W options being enabled and due to a number
of -D options being configured/required by my platform.

By defining QUIET_MAKE (e.g. make QUIET_MAKE=YesPlease) during
compilation users will get a less verbose output, such as:

    ...
    CC builtin-grep.c
builtin-grep.c:187: warning: 'external_grep' defined but not used
    CC builtin-init-db.c
    CC builtin-log.c
    CC builtin-ls-files.c
    CC builtin-ls-tree.c
    ...

The verbose (normal make) output is still the default.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-06 00:48:13 -08:00
ba66c58637 Merge branch 'maint'
* maint:
  git-gui: Make 'make' quieter by default
  git-gui: Remove unnecessary /dev/null redirection.
  git-gui: Don't create empty (same tree as parent) commits.
  git-gui: Add Reset to the Branch menu.
  git-gui: Relocate the menu/transport menu code.
2007-03-06 00:45:34 -08:00
c044aa18f6 git-bundle: fix pack generation.
The handcrafted built-in rev-list lookalike forgot to mark the trees
and blobs contained in the boundary commits uninteresting, resulting
in unnecessary objects in the pack.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-05 23:28:36 -08:00
31930b5bee Merge branch 'maint'
* maint:
  git-commit: cd to top before showing the final stat
2007-03-05 23:11:54 -08:00
0e6240447c cherry-pick: Bug fix 'cherry picked from' message.
Somewhere along the line (in abd6970a) git-revert.sh learned to
omit the private object name from the new commit message *unless*
-x was supplied on the command line by the user.

The way this was implemented is really non-obvious in the original
script.  Setting replay=t (the default) means we don't include the
the private object name, while setting reply='' (the -x flag) means
we should include the private object name.  These two settings now
relate to the replay=1 and replay=0 cases in the C version, so we
need to negate replay to test it is 0.

I also noticed the C version was adding an extra LF in the -x case,
where the older git-revert.sh was not.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-05 21:55:31 -08:00
99e6ac503b Merge branch 'master-for-junio' of git://repo.or.cz/git/fastimport; branch 'maint'
* 'master-for-junio' of git://repo.or.cz/git/fastimport:
  fast-import: Fail if a non-existant commit is used for merge
  fast-import: Avoid infinite loop after reset

* maint:
  Fix diff-options references in git-diff and git-format-patch
  Add definition of <commit-ish> to the main git man page.
  Begin SubmittingPatches with a check list
  fast-import: Fail if a non-existant commit is used for merge
  fast-import: Avoid infinite loop after reset
2007-03-05 21:23:46 -08:00
6b4318e604 Merge branch 'maint'
* maint:
  fast-import: Fail if a non-existant commit is used for merge
  fast-import: Avoid infinite loop after reset

[sp: Minor evil merge to deal with type_names array moving
 to be private in 'master'.]
2007-03-05 12:50:29 -05:00
e2b4f63512 fsck: exit with non-zero status upon errors
git-fsck always exited with status 0, which was a bit sloppy.
This makes it exit with a non-zero status when errors are
found.  The error code is an OR'ed result of:

  1 if corrupted objects are found.
  2 if objects that are ought to be reachable are missing or corrupt.

For example, it would exit with 1 in a repository with an
unreachable corrupt object.  If a tree object of the HEAD commit
is corrupt, you would get 3.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-05 00:55:19 -08:00
7efbff7531 unpack_sha1_file(): detect corrupt loose object files.
We did not detect broken loose object files, either when
underlying inflate() signalled the breakage, nor inflate()
finished and we had garbage trailing at the end.  We do better
now.

We also make unpack_sha1_file() a static function to
sha1_file.c, since it is not used by anybody outside.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-05 00:55:19 -08:00
efec43c028 fsck: fix broken loose object check.
When "git fsck" without --full found a loose object missing
because it was broken, it mistakenly thought it was not parsed
because we found it in one of the packs.  Back when this code
was written, we did not have a way to explicitly check if we
have the object in pack, but we do now.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-05 00:55:19 -08:00
5ced057221 contrib/emacs: Use non-interactive function to byte-compile files
Add git-blame as a candidate to the byte-compilation.

batch-byte-compile is the prefered way to byte-compile files in
batch mode. Use it instead of the interactive function.

Signed-off-by: Xavier Maillard <zedek@gnu.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-05 00:45:57 -08:00
ac3ec0d555 t/t5515-fetch-merge-logic.sh: Added tests for the merge login in git-fetch
Signed-off-by: Santi Béjar <sbejar@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-05 00:27:37 -08:00
46d49472f4 Post 1.5.0.3 cleanup
Update the main git.html page to point at 1.5.0.3 documentation.
Update draft 1.5.1 release notes with what we have so far.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 22:49:10 -08:00
33ee4cfb69 format-patch --attach: not folding some long headers.
Panagiotis Issaris reports that some MUAs seem not to like
folded "content-type" and "content-disposition" headers, so this
makes format-patch --attach output to avoid them.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 17:31:29 -08:00
c112f689c2 format-patch: add --inline option and make --attach a true attachment
The existing --attach option did not create a true "attachment"
but multipart/mixed with Content-Disposition: inline.  It should
have been with Content-Disposition: attachment.

Introduce --inline to add multipart/mixed that is inlined, and
make --attach to create an attachement.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 17:31:29 -08:00
3ddad98b74 Merge branch 'js/fetch-progress' (early part)
* 'js/fetch-progress' (early part):
  Fixup no-progress for fetch & clone
  fetch & clone: do not output progress when not on a tty

Conflicts:

	git-fetch.sh
2007-03-04 17:31:21 -08:00
e6f9511343 Merge branch 'js/symlink'
* js/symlink:
  Tell multi-parent diff about core.symlinks.
  Handle core.symlinks=false case in merge-recursive.
  Add core.symlinks to mark filesystems that do not support symbolic links.
2007-03-04 17:31:09 -08:00
784b11cd05 Merge branch 'maint'
* maint:
  GIT 1.5.0.3
  glossary: Add definitions for dangling and unreachable objects
  user-manual: more detailed merge discussion
  user-manual: how to replace commits older than most recent
  user-manual: insert earlier of mention content-addressable architecture
  user-manual: ensure generated manual references stylesheet
  user-manual: reset to ORIG_HEAD not HEAD to undo merge
  Documentation: mention module option to git-cvsimport
2007-03-04 17:24:49 -08:00
f98ef68faf .gitignore: add git-fetch--tool
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 15:36:08 -08:00
f52463a582 cherry-pick: Suggest a better method to retain authorship
When a cherry-pick failed, we used to recommend setting environment
variables to retain the authorship. It is much easier, though, to use
the "-c" flag of git-commit.

Print this message also when merge-recursive fails (the code used to
exit(1) in that case, never reaching the proper failure path).

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 13:15:09 -08:00
102a0a2db1 git-svn: fix show-ignore when not connected to the repository root
It was traversing the entire repository before.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 00:34:01 -08:00
5bd74506cd Get rid of the dependency to GNU diff in the tests
Now that "git diff" handles stdin and relative paths outside the
working tree correctly, we can convert all instances of "diff -u"
to "git diff".

This commit is really the result of

$ perl -pi.bak -e 's/diff -u/git diff/' $(git grep -l "diff -u" t/)

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>

(cherry picked from commit c699a40d68215c7e44a5b26117a35c8a56fbd387)
2007-03-04 00:24:15 -08:00
0c725f1bd9 diff --no-index: support /dev/null as filename
This allows us to create "new file" and "delete file" patches.
It also cleans up the code.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 00:20:31 -08:00
3afaa72d7d diff-ni: fix the diff with standard input
The earlier commit to read from stdin was full of problems, and
this corrects them.

 - The mode bits should have been set to satisify S_ISREG(); we
   forgot to the S_IFREG bits and hardcoded 0644;
 - We did not give escape hatch to name a path whose name is
   really "-".  Allow users to say "./-" for that;
 - Use of xread() was not prepared to see short read (e.g. reading
   from tty) nor handing read errors.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-04 00:17:27 -08:00
5332b2af10 diff: support reading a file from stdin via "-"
This allows you to say

	echo Hello World | git diff x -

to compare the contents of file "x" with the line "Hello World".
This automatically switches to --no-index mode.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-03 23:45:47 -08:00
ae792aa52b diff-ni: allow running from a subdirectory.
When run from a subdirectory of a repository, the command forgot
to adjust paths given to it with prefix.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-03 23:45:14 -08:00
9509af686b Make git-revert & git-cherry-pick a builtin
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-03 22:59:34 -08:00
e551208dea Merge branch 'js/diff-ni' (early part)
* 'js/diff-ni' (early part):
  diff: make more cases implicit --no-index
2007-03-03 22:51:46 -08:00
118f8b2413 git-config: document --rename-section, provide --remove-section
This patch documents the previously undocumented option --rename-section
and adds a new option to zap an entire section.

Signed-off-by: Paolo Bonzini <bonzini@gnu.org>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-03 19:59:37 -08:00
253e772ede Merge branch 'maint'
* maint:
  Unset NO_C99_FORMAT on Cygwin.
  Fix a "pointer type missmatch" warning.
  Fix some "comparison is always true/false" warnings.
  Fix an "implicit function definition" warning.
  Fix a "label defined but unreferenced" warning.
  Document the config variable format.suffix
  git-merge: fail correctly when we cannot fast forward.
  builtin-archive: use RUN_SETUP
  Fix git-gc usage note
2007-03-03 19:47:46 -08:00
a249a9b5a2 Tell multi-parent diff about core.symlinks.
When core.symlinks is false, and a merge of symbolic links had conflicts,
the merge result is left as a file in the working directory. A decision
must be made whether the file is treated as a regular file or as a
symbolic link. This patch treats the file as a symbolic link only if
all merge parents were also symbolic links.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-03 19:30:34 -08:00
723024d696 Handle core.symlinks=false case in merge-recursive.
If the file system does not support symbolic links (core.symlinks=false),
merge-recursive must write the merged symbolic link text into a regular
file.

While we are here, fix a tiny memory leak in the if-branch that writes
real symbolic links.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-03 18:59:41 -08:00
78a8d641c1 Add core.symlinks to mark filesystems that do not support symbolic links.
Some file systems that can host git repositories and their working copies
do not support symbolic links. But then if the repository contains a symbolic
link, it is impossible to check out the working copy.

This patch enables partial support of symbolic links so that it is possible
to check out a working copy on such a file system.  A new flag
core.symlinks (which is true by default) can be set to false to indicate
that the filesystem does not support symbolic links. In this case, symbolic
links that exist in the trees are checked out as small plain files, and
checking in modifications of these files preserve the symlink property in
the database (as long as an entry exists in the index).

Of course, this does not magically make symbolic links work on such defective
file systems; hence, this solution does not help if the working copy relies
on that an entry is a real symbolic link.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-02 16:58:05 -08:00
4808bec6f9 Merge branch 'maint'
* maint:
  Fix quoting in update hook template
2007-03-02 16:57:53 -08:00
5e00f6faf4 git-branch: document new --no-abbrev option
Add the new --no-abbrev option to the man page for the git-branch command.

Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-02 16:39:18 -08:00
43bc820db7 git-branch: improve abbreviation of sha1s in verbose mode
git-branch has an --abbrev= command line option, but it does
no checking of the input.  Take the argument parsing code from
setup_revisions in revisions.c, and also the code for parsing
the --no-abbrev option.

Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-02 16:38:47 -08:00
62273826fe print_wrapped_text: fix output for negative indent
When providing a negative indent, it means that -indent columns were
already printed. Fix a bug where the function ate the first character
if already the first word did not fit into the first line.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-02 15:14:48 -08:00
3d84df43e1 Sample update hook: typofix and modernization to use "git log"
Instead of using antiquated "git-rev-parse | git-rev-list"
pipeline, it is easier to use "git-rev-list" or "git-log" these
days, as Linus points out.

While we are at it, fix the typo on variable name $newref that
should be $newrev.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-02 15:06:25 -08:00
8ab3e18586 Merge branch 'js/commit-format'
* js/commit-format:
  show_date(): rename the "relative" parameter to "mode"
  Actually make print_wrapped_text() useful
  pretty-formats: add 'format:<string>'
2007-03-02 00:37:12 -08:00
8b969a5fb5 Merge branch 'maint'
* maint:
  Another memory overrun in http-push.c
  fetch.o depends on the headers, too.
  Documentation: Correct minor typo in git-add documentation.
  Documentation/git-send-email.txt: Fix labeled list formatting
  Documentation/git-quiltimport.txt: Fix labeled list formatting
  Documentation/build-docdep.perl: Fix dependencies for included asciidoc files
2007-03-02 00:31:51 -08:00
112f63851b Documentation/git-svn.txt: Fix formatting errors
Fix some formatting problems:

  - Some list labels were missing their "::" characters.
  - Some of continuation paragraphs in labeled lists were incorrectly
    formatted as literal paragraphs.
  - In one case "[verse]" was missing before the config key list.
  - The "Basic Examples" section was incorrectly nested inside the
    "Config File-Only Options" section.

Signed-off-by: Sergey Vlasov <vsu@altlinux.ru>
Acked-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-01 13:25:59 -08:00
20f50f1670 fix various doc typos
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-03-01 03:27:36 -08:00
855b34680e builtin-fetch--tool: fix reflog notes.
Also the verbose output had unnecessary SHA1 and not-for-merge markers
leaked because append_fetch_head() cheated

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-28 17:02:18 -08:00
e6eebbb3ae git-fetch: retire update-local-ref which is not used anymore.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-28 17:01:00 -08:00
fcfa33ec90 diff: make more cases implicit --no-index
When specifying an absolute path, or a relative path pointing outside
the working tree, do not fail, but roll your own diffopt parsing,
and execute a --no-index diff.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-28 16:32:31 -08:00
2eb06531e3 Add recent changes to draft 1.5.1 release notes.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-28 15:06:38 -08:00
16d53152f1 Merge branch 'js/commit-by-name'
* js/commit-by-name:
  object name: introduce ':/<oneline prefix>' notation
2007-02-28 14:56:08 -08:00
77b50ab009 Merge branch 'js/bundle'
* js/bundle:
  bundle: reword missing prerequisite error message
  git-bundle: record commit summary in the prerequisite data
  git-bundle: fix 'create --all'
  git-bundle: avoid fork() in verify_bundle()
  git-bundle: assorted fixes
  Add git-bundle: move objects and references by archive
2007-02-28 14:38:36 -08:00
1db8b60b2a Merge branch 'maint'
* maint:
  Start preparing Release Notes for 1.5.0.3
  Documentation: git-remote add [-t <branch>] [-m <branch>] [-f] name url
  Include config.mak in doc/Makefile
  git.el: Set the default commit coding system from the repository config.
  git-archimport: support empty summaries, put summary on a single line.
  http-push.c::lock_remote(): validate all remote refs.
  git-cvsexportcommit: don't cleanup .msg if not yet committed to cvs.
2007-02-28 14:18:57 -08:00
d0d8e14d1b index_fd(): convert blob only if it is a regular file.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-28 12:00:00 -08:00
53bca91a7d index_fd(): pass optional path parameter as hint for blob conversion
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-28 12:00:00 -08:00
edaec3fbe8 index_fd(): use enum object_type instead of type name string.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-28 12:00:00 -08:00
597388f6a1 Merge branch 'np/types'
* np/types:
  Cleanup check_valid in commit-tree.
  make sure enum object_type is signed
  get rid of lookup_object_type()
  convert object type handling from a string to a number
  formalize typename(), and add its reverse type_from_string()
  sha1_file.c: don't ignore an error condition in sha1_loose_object_info()
  sha1_file.c: cleanup "offset" usage
  sha1_file.c: cleanup hdr usage
2007-02-28 11:58:27 -08:00
c7d68c8000 builtin-fetch--tool: make sure not to overstep ls-remote-result buffer.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 23:51:48 -08:00
fbe3d87e5f Merge branch 'mc/sendmail'
* mc/sendmail:
  git-send-email: abort/usage on bad option
2007-02-27 22:23:40 -08:00
25a0b20c74 Merge branch 'js/diff-ni' (early part)
* 'js/diff-ni' (early part):
  diff --no-index: also imitate the exit status of diff(1)
  Fix typo: do not show name1 when name2 fails
  Teach git-diff-files the new option `--no-index`
  run_diff_{files,index}(): update calling convention.
  update-index: do not die too early in a read-only repository.
  git-status: do not be totally useless in a read-only repository.
2007-02-27 22:18:22 -08:00
c4f8f82755 Merge branch 'maint'
* maint:
  builtin-fmt-merge-msg: fix bugs in --file option
  index-pack: Loop over pread until data loading is complete.
  blameview: Fix the browse behavior in blameview
  Fix minor typos/grammar in user-manual.txt
  Correct ordering in git-cvsimport's option documentation
  git-show: Reject native ref
  Fix git-show man page formatting in the EXAMPLES section
2007-02-27 22:15:42 -08:00
66035a6b3d Cleanup check_valid in commit-tree.
This routine should be using the object_type enum rather than a
string comparsion, as the expected type is always supplied and is
known at compile time.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 21:40:18 -08:00
fef742c4ed make sure enum object_type is signed
This allows for keeping the common idiom which consists of using
negative values to signal error conditions by ensuring that the enum
will be a signed type.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 21:37:46 -08:00
1b0baf1401 git-send-email: abort/usage on bad option
Instead of proceeding, abort and give usage message when a bad option
is seen.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 21:30:38 -08:00
f8493ec09b show_date(): rename the "relative" parameter to "mode"
Now, show_date() can print three different kinds of dates: normal,
relative and short (%Y-%m-%s) dates.

To achieve this, the "int relative" was changed to "enum date_mode
mode", which has three states: DATE_NORMAL, DATE_RELATIVE and
DATE_SHORT.

Since existing users of show_date() only call it with relative_date
being either 0 or 1, and DATE_NORMAL and DATE_RELATIVE having these
values, no behaviour is changed.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 17:29:37 -08:00
094e03b039 Actually make print_wrapped_text() useful
Now, it returns the current column, does not add a newline, and you can
pass a negative indent, to indicate that the indent was already printed.

With this, you can actually continue in the middle of a paragraph, not
having to print everything into a buffer first.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 17:29:02 -08:00
dec56c8cf1 fetch--tool: fix uninitialized buffer when reading from stdin
The original code allocates too much space and forgets to NUL
terminate the string.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 16:12:23 -08:00
8538e876b1 cvsserver: Make always-binary mode a config file option
The config option gitcvs.allbinary may be set to force all entries to
get the -kb flag.

In the future the gitattributes system will probably be a more
appropriate way of doing this, but that will easily slot in as the
entries lines sent to the CVS client now have their kopts set via the
function kopts_from_path().

In the interim it might be better to not just have a all-or-nothing
approach, but rather detect based on file extension (or file contents?).
That would slot in easily here as well.  However, I personally prefer
everything to be binary-safe, so I just switch the switch.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 16:01:58 -08:00
1872adabcc cvsserver: Remove trailing "\n" from commithash in checkin function
The commithash for updating the ref is obtained from a call to
git-commit-tree.  However, it was returned (and stored) with the
trailing newline.  This meant that the later call to git-update-ref that
was trying to update to $commithash was including the newline in the
parameter - obviously that hash would never exist, and so git-update-ref
would always fail.

The solution is to chomp() the commithash as soon as it is returned by
git-commit-tree.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 15:51:03 -08:00
ada5ef3b48 Make 'cvs ci' lockless in git-cvsserver by using git-update-ref
This makes "ci" codepath lockless by following the usual
"remember the tip, do your thing, then compare and swap at the
end" update pattern using update-ref.  Incidentally, by updating
the code that reads where the tip of the head is to use
show-ref, it makes it safe to use in a repository whose refs are
pack-pruned.

I noticed that other parts of the program are not yet pack-refs
safe, but tried to keep the changes to the minimum.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 15:44:40 -08:00
dcf01c6e6b builtin-fetch--tool: adjust to updated sha1_object_info().
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 02:39:51 -08:00
88459358cd Merge branch 'np/types' into jc/fetch
* np/types: (253 commits)
  get rid of lookup_object_type()
  convert object type handling from a string to a number
  formalize typename(), and add its reverse type_from_string()
  sha1_file.c: don't ignore an error condition in sha1_loose_object_info()
  sha1_file.c: cleanup "offset" usage
  sha1_file.c: cleanup hdr usage
  git-apply: do not fix whitespaces on context lines.
  diff --cc: integer overflow given a 2GB-or-larger file
  mailinfo: do not get confused with logical lines that are too long.
  Documentation: link in 1.5.0.2 material to the top documentation page.
  Documentation: document remote.<name>.tagopt
  GIT 1.5.0.2
  git-remote: support remotes with a dot in the name
  Documentation: describe "-f/-t/-m" options to "git-remote add"
  diff --cc: fix display of symlink conflicts during a merge.
  merge-recursive: fix longstanding bug in merging symlinks
  merge-index: fix longstanding bug in merging symlinks
  diff --cached: give more sensible error message when HEAD is yet to be created.
  Update tests to use test-chmtime
  Add test-chmtime: a utility to change mtime on files
  ...
2007-02-27 02:27:26 -08:00
0ab179504a get rid of lookup_object_type()
This function is called only once in the whole source tree.  Let's move
its code inline instead, which is also in the spirit of removing as much
object type char arrays as possible (not that this patch does anything for
that but at least it is now a local matter).

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 01:34:21 -08:00
21666f1aae convert object type handling from a string to a number
We currently have two parallel notation for dealing with object types
in the code: a string and a numerical value.  One of them is obviously
redundent, and the most used one requires more stack space and a bunch
of strcmp() all over the place.

This is an initial step for the removal of the version using a char array
found in object reading code paths.  The patch is unfortunately large but
there is no sane way to split it in smaller parts without breaking the
system.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 01:34:21 -08:00
df8436622f formalize typename(), and add its reverse type_from_string()
Sometime typename() is used, sometimes type_names[] is accessed directly.
Let's enforce typename() all the time which allows for validating the
type.

Also let's add a function to go from a name to a type and use it instead
of manual memcpy() when appropriate.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 01:34:21 -08:00
9ba630318f sha1_file.c: don't ignore an error condition in sha1_loose_object_info()
Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 01:34:21 -08:00
2b87c45ba6 sha1_file.c: cleanup "offset" usage
First there are too many offsets there and it is getting confusing.
So 'offset' is now 'curpos' to distinguish from other offsets like
'obj_offset'.

Then structures like x = foo(x, &y) are now done as y = foo(&x).
It looks more natural that the result y be returned directly and
x be passed as reference to be updated in place.  This has the effect
of reducing some line length and removing a few, needing a bit less
stack space, and it even reduces the compiled code size.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 01:34:21 -08:00
d65a16f6c4 sha1_file.c: cleanup hdr usage
Let's have hdr be a simple char pointer/array when possible, and let's
reduce its storage to 32 bytes.  Especially for sha1_loose_object_info()
where 128 bytes is way excessive and wastes extra CPU cycles inflating.

The object type is already restricted to 10 bytes in parse_sha1_header()
and the size, even if it is 64 bits, will fit in 20 decimal numbers.  So
32 bytes is plenty.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-27 01:34:21 -08:00
4e4b55dd0f Merge branch 'maint'
* maint:
  git-apply: do not fix whitespaces on context lines.
  diff --cc: integer overflow given a 2GB-or-larger file
  mailinfo: do not get confused with logical lines that are too long.
2007-02-27 01:33:52 -08:00
34a5e1a2d9 diff --no-index: also imitate the exit status of diff(1)
diff sets the exit status to 0 when no changes were found, to 1
when changes were found, and 2 means error.

We imitate this to be able to use "git diff" in the test scripts.
(Actually, keeping in line with the rest of git, -1 is returned
on error, which corresponds to an exit status 255).

To find out if the diff is not empty, a member called
"found_changes" was introduced in struct diff_options, which is
set in builtin_diff() and fn_out_consume().

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-26 01:20:55 -08:00
048f48a2fd Merge branch 'master' into js/diff-ni
* master: (201 commits)
  Documentation: link in 1.5.0.2 material to the top documentation page.
  Documentation: document remote.<name>.tagopt
  GIT 1.5.0.2
  git-remote: support remotes with a dot in the name
  Documentation: describe "-f/-t/-m" options to "git-remote add"
  diff --cc: fix display of symlink conflicts during a merge.
  merge-recursive: fix longstanding bug in merging symlinks
  merge-index: fix longstanding bug in merging symlinks
  diff --cached: give more sensible error message when HEAD is yet to be created.
  Update tests to use test-chmtime
  Add test-chmtime: a utility to change mtime on files
  Add Release Notes to prepare for 1.5.0.2
  Allow arbitrary number of arguments to git-pack-objects
  rerere: do not deal with symlinks.
  rerere: do not skip two conflicted paths next to each other.
  Don't modify CREDITS-FILE if it hasn't changed.
  diff-patch: Avoid emitting double-slashes in textual patch.
  Reword git-am 3-way fallback failure message.
  Limit filename for format-patch
  core.legacyheaders: Use the description used in RelNotes-1.5.0
  ...
2007-02-26 01:20:42 -08:00
c260d790c8 Documentation: link in 1.5.0.2 material to the top documentation page.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-26 01:16:01 -08:00
047f636d90 Documentation: document remote.<name>.tagopt
Update config.txt with info regarding tagopt option

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-26 00:32:48 -08:00
8807d321af Merge branch 'maint'
* maint:
  GIT 1.5.0.2
  git-remote: support remotes with a dot in the name
  Documentation: describe "-f/-t/-m" options to "git-remote add"
  diff --cc: fix display of symlink conflicts during a merge.
2007-02-26 00:32:19 -08:00
5569dad48e Merge branch 'maint'
* maint:
  merge-recursive: fix longstanding bug in merging symlinks
  merge-index: fix longstanding bug in merging symlinks
2007-02-25 19:10:13 -08:00
646b329961 Fix typo: do not show name1 when name2 fails
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-25 14:42:23 -08:00
6c09c45138 diff --cached: give more sensible error message when HEAD is yet to be created.
It is not like the user said 'diff --cached HEAD', so complaining about
HEAD not being a valid commit, while technically might be correct, is
not very helpful.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-25 11:09:56 -08:00
56cf9806a9 Update tests to use test-chmtime
test-lib:
  Make sure test-chmtime has been built before starting.

t4200-rerere:
  Removed non-portable date dependency and avoid touch
  Avoid "test -a" which isn't portable, either

lib-git-svn:
  Use test-chmtime instead of Perl one-liner to poke

Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-25 11:09:56 -08:00
17e4836875 Add test-chmtime: a utility to change mtime on files
This is intended to be a portable replacement for our usage
of date(1), touch(1), and Perl one-liners in tests.

Usage: test-chtime (+|=|-|=+|=-)<seconds> <file>..."

  '+' increments the mtime on the files by <seconds>
  '-' decrements the mtime on the files by <seconds>
  '=' sets the mtime on the file to exactly <seconds>
  '=+' and '=-' sets the mtime on the file to <seconds> after or
      before the current time.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-25 11:09:56 -08:00
2c7ca1fcf1 Merge branch 'maint'
* maint:
  Add Release Notes to prepare for 1.5.0.2
  Allow arbitrary number of arguments to git-pack-objects
  rerere: do not deal with symlinks.
  rerere: do not skip two conflicted paths next to each other.
  Don't modify CREDITS-FILE if it hasn't changed.
2007-02-25 11:08:47 -08:00
fee7c2c71d git-fetch--tool takes flags before the subcommand.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-24 04:35:31 -08:00
efdfd6c8d4 Evil Merge branch 'jc/status' (early part) into js/diff-ni
* 'jc/status' (early part):
  run_diff_{files,index}(): update calling convention.
  update-index: do not die too early in a read-only repository.
  git-status: do not be totally useless in a read-only repository.

This is to resolve semantic conflict (which is not textual) that
changes the calling convention of run_diff_files() early.
2007-02-24 02:20:13 -08:00
28a4d94044 object name: introduce ':/<oneline prefix>' notation
To name a commit, you can now say

	$ git rev-parse ':/Initial revision of "git"'

and it will return the hash of the youngest commit whose
commit message (the oneline) begins with the given prefix.

For future extension, a leading exclamation mark is treated
specially: if you want to match a commit message starting with
a '!', just repeat the exclamation mark. So, to match a commit
which starts with '!Hello World', use

	$ git show ':/!!Hello World'

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-24 02:06:18 -08:00
7bd59dee5b Merge branch 'js/apply'
* js/apply:
  apply: make --verbose a little more useful
2007-02-24 02:00:32 -08:00
503ca3a9f2 Merge branch 'js/no-limit-boundary'
* js/no-limit-boundary:
  rev-list --max-age, --max-count: support --boundary
2007-02-24 01:47:56 -08:00
cc58fc0684 Merge branch 'js/etc-config'
* js/etc-config:
  Make tests independent of global config files
  config: read system-wide defaults from /etc/gitconfig
2007-02-24 01:43:28 -08:00
8a13becc0d Merge branch 'maint'
* maint:
  diff-patch: Avoid emitting double-slashes in textual patch.
  Reword git-am 3-way fallback failure message.
  Limit filename for format-patch
  core.legacyheaders: Use the description used in RelNotes-1.5.0
  git-show-ref --verify: Fail if called without a reference

Conflicts:

	builtin-show-ref.c
	diff.c
2007-02-24 01:42:06 -08:00
64d99e9c5a bundle: reword missing prerequisite error message
As suggested by Mark Levedahl.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-24 01:16:58 -08:00
b0e908977e Fixup no-progress for fetch & clone
The intent of the commit 'fetch & clone: do not output progress when
not on a tty' was to make fetching and cloning less chatty when
output was not redirected (such as in a cron job).

However, there was a serious thinko in that commit. It assumed that
the client _and_ the server got this update at the same time. But
this is obviously not the case, and therefore upload-pack died on
seeing the option "--no-progress".

This patch fixes that issue by making it a protocol option. So, until
your server is updated, you still see the progress, but once the
server has this patch, it will be quiet.

A minor issue was also fixed: when cloning, the checkout did not
heed no_progress.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-24 00:26:18 -08:00
509b4d73b2 .mailmap maintenance after pulling from git-svn
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-23 03:11:52 -08:00
2e5e24803f git-svn: fix some potential bugs with --follow-parent
When using do_switch:

  We only need to ensure the index is clean and set to that of the
  parent tree) we rely on being able to reconstruct full files
  with deltas transferred over the network.

When using do_update:

  We may safely unlink the index if we are fetching an entire
  new tree with do_update.  Having an old index (from a
  previously deleted/abandoned directory) around can cause
  irrelevant files to be mistakenly kept.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 02:21:59 -08:00
e2c475d91c git-svn: fix reconnections to different paths of svn:// repositories
Clearing the pool of the previous SVN::Ra connection we have
seems to to fix mysterious connection dropping errors when
reconnecting to different paths of svn:// repositories hosted by
rubyforge.org.

Note: I'm not sure *why* this fixes things things,
but it does for me.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 01:59:34 -08:00
f30603fcf3 git-svn: fix clone when a target directory has been specified
Several bugs caused this to fail:

* GIT_DIR was set incorrectly after entering the target directory

* Avoid double chdir-ing when clone is called with an explicit path

* create target subdirectory *before* running git-init when using
  the multi-init path

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 01:26:26 -08:00
a0d7fe3fcd git-svn: document --username
Also, it turns out that SVN::Ra doesn't attempt to deal with
authentication or pass the username to ssh when doing svn+ssh://
URLs

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 01:01:02 -08:00
18ea92bd81 git-svn: don't consider SVN URL usernames significant when comparing
http://foo@blah.com/path is the same as http://blah.com/path, so
remove usernames from URLs before storing them in commits, and when
reading them from commits.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 01:01:02 -08:00
5253dc33b7 git-svn: ensure we're at the top-level and can access $GIT_DIR
If we are run inside a subdirectory of a working tree, we'll
chdir to the top first before touching anything.  This also
prevents the accidental creation of .git directories inside
subdirectories since they need metadata.

Noticed by maio on #git

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
1a97a50604 git-svn: give show-ignore HEAD smarts, like dcommit and log
This allows the user to run git-svn show-ignore on there
current HEAD without needing to remember which branch/ref they
branched from with -i.  Also, find_by_url should correctly
handle cases where the URL passed to it is not valid.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
0dfaf0a4e1 git-svn: allow metadata options to be specified with 'init' and 'clone'
Since the options that affect the way metadata is handled in
git-svn, should be consistently set/unset throughout history
imported by git-svn; it makes sense to allow the user to set
certain options from the command-line that will write to the
config file when initially creating the repository.

Also, fix some formatting issues while we're updating
documentation.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
a81ed0b63e git-svn: documentation updates
This documents the 'clone' and 'rebase' commands
of git-svn.   Additionaly, examples are updated
to use them instead of the lower-level 'init' and
'fetch' commands.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
e2b36f6018 git-svn: add test for useSvnsyncProps
These tests are very similar as the ones I used for useSvmProps
and expect the same results because both dumps were generated
from the same original repo.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
befc9adc0c git-svn: fix useSvmProps, hopefully for the last time
svm:mirror is not useful at all for us.  Parts of the old unit
test were broken and based on my misunderstanding of the
svm:mirror property.

When we read svm:source; make sure we correctly handle the '!'
in it: it is used to separate the path of the repository root
from the virtual path within the repository.  We don't need
to make that distinction, honestly!

We also ensure that subdirectories are also mirrored with the
correct URL if we're using useSvmProps.

We have a new test that uses dumped repo that was really
created using SVN::Mirror to avoid ambiguities and
mis-understandings about the svm: properties.

Note: trailing whitespace in the svm.dump file is unfortunately
a reality and required by SVN; so please ignore it when applying
this patch.

Also, ensure that the -R/--remote/--svn-remote flag is always
in effect if explicitly passed via the command-line.  This
allows us to track logically different mirrors sharing the
same URL (probably common with SVN::Mirror/SVK users).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
62e349d235 git-svn: add support for using svnsync properties
This is similar to useSvmProps, but far simpler in
implementation because svnsync retains a 1:1
between revision numbers and relative paths within
the repository

Config keys: svn.useSvnsyncProps
             svn-remote.<repo>.useSvnsyncProps

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
aea736cc6d git-svn: allow overriding of the SVN repo root in metadata
This feature allows users to create repositories from alternate
URLs.  For example, an administrator could run git-svn on the
server locally (accessing via file://) but wish to distribute
the repository with a public http:// or svn:// URL in the
metadata so users of it will see the public URL.

Config key: svn-remote.<remote>.rewriteRoot

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
0425ea9088 git-svn: add 'clone' command, an alias for init + fetch
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
b7e5348c7f git-svn: hide the private git-svn 'config' file as '.metadata'
Having it named as 'config' prevents us from tracking a
ref named 'config', which is a huge mistake.

On the non-technical side, the word 'config' implies that
a user can freely modify it; but that's not the case
here.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
d6d3346bab git-svn: fix some issues for people migrating from older versions
* Fixed logic for renaming old .rev_db -> .rev_db.$uuid

 * correctly handle manual migrations for those who decide to
   start use globbing to handle branches/tags over individual
   'fetch' keys

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
905f8b7dfc git-svn: add a 'rebase' command
This works similarly to 'svn update' or 'git pull' except that
it preserves linear history with 'git rebase' instead of 'git
merge' for ease of dcommit-ing with git-svn.

While we're at it, put the working_head_info() logic
into its own function and allow --fetch-all/--all for
dcommit and rebase (which will fetch all refs in the
current [svn-remote] instead of just the working one).

Note that the '-a' switch (short for --fetch-all/--all) has been
removed as it conflicts with the non-svn 'git fetch'

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
1e889ef36c git-svn: checkout files on new fetches
On newly-created repositories, 'refs/heads/master' does not
point to anything.  This can be confusing to new users; so we
update 'master' to point to the last imported ref after fetching
is done.

Once 'master' is valid; we assume HEAD points to it; and if
the repository is not bare, then checkout the files if the
working tree is clean and unused.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
488a63ec23 git-svn: add support for --stat in the log command
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
a836a0e172 git-svn: documentation updates for new functionality
Force the showing of the --minimize flag as an option in the
'migrate' help.

Also, fix the usage function to correctly filter out
the deprecated aliases.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
60d9c97adf git-svn: allow dcommit for those who only fetch from SVM with useSvmProps
This allows users to use SVM (SVN::Mirror) to mirror a remote
repository to use dcommit to commit to the repository that SVM
was mirroring.  When dcommit is used in this manner, the automatic
fetch + rebase/reset does not happen; in which case the user will
have to manually invoke svm/svk, run 'git svn fetch', and finally
'git rebase'.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
7447b4bc83 git-svn: error checking for invalid [svn-remote "..."] sections
We don't end up trying to pass an undef URL over to SVN::Ra->new
because it'll segfault.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:13 -08:00
e8d120bd5a git-svn: remember to check for clean indices on globbed refs, too
Also, warn about dirty indices and avoid an unncessary
write-tree call if the index is clean.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
6af1db447b git-svn: allow --log-window-size to be specified, default to 100
The newer default value should should lower memory usage for
large fetches and also help with fetching from less reliable
servers.  Previously the value was 1000 and memory usage
got a bit high on some repositories and fetching became
less reliable in some cases.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
b4d57e5ea3 git-svn: simplify the (multi-)init methods of fetching
Also, some changes to avoid creating dead dirs under
.git/svn/.  We now create all directories as late as
possible.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
28710f74ea git-svn: brown paper bag fixes
* avoid skipping modification-only changes in fetch
  * correctly fetch when we only have branches and tags
    to glob from (no fetch keys defined)

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
dadc6d2a09 git-svn: allow 'init' to act as multi-init
multi-init is now just an alias that requires -T/-t/-b;
all options that 'init' can now accept.

This will hopefully simplify usage and reduce typing.

Also, allow the --shared option in 'init' to take an optional
argument now that 'git-init --shared' supports an optional
argument.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
e98671e5c2 git-svn: hopefully make 'fetch' more user-friendly
multi-fetch is deprecated, "fetch -a" is easier to type
By default, fetch will fetch everything from its default
[svn-remote]; if fetch [--all|-a] is specified, then it will
fetch from all svn remotes.  Refspecs on the command-line
(like git-fetch) are not supported.

Also, enable -r/--revision arguments for fetch so
users can shoot themselves in the foot^W^W^W^W^W
skip some history and do the equivalent of a shallow
clone/fetch they're not interested in.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
ccb6b6f5b5 t910*: s/repo-config/config/g; poke around possible race conditions
Some of the repo-config => config renaming missed the git-svn
tests; so I'm just renaming them to be consisten with the
rest of the modern git.

Also, some of the newer tests didn't have 'poke' in them
to workaround race conditions on fast machines.  This adds
places where they can _possibly_ occur; but I don't have
fast enough hardware to trigger them.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
3bc718ba66 git-svn: usability fixes for the 'git svn log' command
Similar in spirit to the recent dcommit change, we now
look at 'HEAD' by default to look for a GIT_SVN_ID
so the user won't have to pass -i <GIT_SVN_ID> argument.

We are also more tolerant of of people passing bare remote names
as a result (just $GIT_SVN_ID without the -i)

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
ce207c7ad1 git-svn: include merges when calling rev-list for decommit
Merge commits can be created when following certain parents,
(most notably 'R' cases) and we definitely don't want to exclude
them.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
a8ae26235c git-svn: make dcommit usable for glob users
* dcommit no longer requires the correct -i/GIT_SVN_ID option
   passed to it.  Since you're committing from HEAD (or another
   commit that is a parent of HEAD), you'll be able to find
   a commit with metadata information containing the SVN URL
   that your HEAD was descended from anyways.

 * I don't think dcommit ever worked for people using the
   noMetadata option; so I don't think relying on metadata
   is an issue.

 * useSvmProps users shouldn't commit to SVN::Mirror created
   repositories anyways, right?

 * Users of globbing should automatically be able to commit
   to paths that are not explicitly set in .git/config

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
2edb9c5cf9 git-svn: make test for SVK mirror path import
A manual test that sets up a repository that looks like an SVK depot,
and then imports it to check that it looks like we mirrored the
'original' source.

There is also a minor modification to the git-svn test library shell
file which sets a variable for the subversion repository's filesystem
path.

[ew: made some of the tests stricter and more thorough]

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
db03cd24a1 git-svn: handle multi-init without --trunk, UseSvmProps fixes
multi-init did not write a svn-remote.<remote>.url config
entry without a --trunk argument.

Also, The svm:mirror property is used by SVN::Mirror to track
the path of the repository that we are mirroring.  We need to
append that to the source (which is (presumably) just the URL of
the repository root).

Lastly, we now look harder for svm:(source|mirror|uuid) properties
in sub and parent directories.  Since our relative path could
be tweaked.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
c3560e535c git-svn: write the highest maxRex out for branches and tags
Even if nothing touched paths we care about in a fetch;
increment the maxRev like we do with rev_db since
we don't like having to run get_log on revisions we've
seen before.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
26a62d57a2 git-svn: use separate, per-repository .rev_db files
We need a separate .rev_db file for each repository we're
tracking.  This allows us to track the same logical path off
multiple mirrors.  We preserve a symlink to the old .rev_db
(no-UUID) if we're (auto-)migrating from an old version to
preserve backwards compatibility.

Also, get rid of the uuid() wrapper since we cache UUID in our
private config, and the SVN::Ra::get_uuid() function memoizes
the return value per-connection.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
97ae091169 git-svn: extra safety for noMetadata and useSvmProps users
Make sure we flush our userspace buffers and and fsync(2)
.rev_db information to disk if we use these options because
we really don't want to lose this information.

Also, disallow --use-svm-props and --no-metadata from the
command-line because history will be inconsistent if they're
only used occasionally.  If a user wants to use these options,
they must be set in the config so they're always on.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
93f2689ccd git-svn: use private $GIT_DIR/svn/config file more
Switch max_rev storage over to using it for globbing
branches and tags.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
91b03282b5 git-svn: add support for per-[svn-remote "..."] options
Available options are currently:

  svn-remote.<remote>.{noMetadata,useSvmProps,followParent}

These boolean switches will override options set globally in
[svn], and even override options set on the command-line (this
should probably change in the future, however).

Note that the noMetadata and useSvmProps options conflict.  It's
both technically and logically impossible to use them together.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
8a49ee9759 git-svn: add support for SVN::Mirror/svk using revprops for metadata
Pass --use-svm-props or set the svn.usesvmprops key with git-config
to enable using properties set by SVN::Mirror when it mirrored the
upstream URL.

This is heavily based on work from Sam Vilain:
> From: Sam Vilain <sam@vilain.net>
> Date: Sun, 11 Feb 2007 12:34:45 +1300
> Subject: [PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths
>
> If an SVN revision has a property, "svm:headrev", it is likely that
> the revision was created by SVN::Mirror (a part of SVK).  The property
> contains a repository UUID and a revision.  We want to make it look
> like we are mirroring the original URL, so introduce a helper function
> that returns the original identity URL and UUID, and use it when
> generating commit messages.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
490f49ea58 git-svn: remove optimized commit stuff for set-tree
I may resurrect it for dcommit at some point, but nobody really
uses set-tree anymore and I don't feel like introducing more
complexity into the code at this point.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
74a81227f9 git-svn: correctly handle globs with a right-hand-side path component
Several bugs were found and fixed while getting this to work:

 * Remember the 'R'(eplace) case of actions and treat it like we
   would an 'A'(dd) case.

 * Fix a small case of follow-parent missing a parent if a
   subdirectory was modified in the revision where the parent was
   copied.

 * dirents returned by get_dir sometimes expire if the data
   structure is too big and the pool is destroyed, so we
   cache get_dir (along with check_path and get_revprops)
   temporarily along with its pool.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
9e3cdbd4f2 git-svn: correctly handle the -q flag in SVN::Git::Fetcher
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
4e9f6cc78e git-svn: fix buggy regular expression usage in several places
I incorrectly used $path/? and $path/* to strip off leading
directories, but places where $path = 'branches/0.17' would
incorrectly strip changes to 'branches/0.17.1' as well.

For globs, we require that our '*' is its own path component
(surrounded by '/' or nothing).  Enforce this when --prefix= is
passed to us, too.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:12 -08:00
0bed5eaa0e git-svn: enable follow-parent functionality by default
--no-follow-parent disables and reverts it back to the old
default behavior of not following parents (if you don't care for
full history).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
e20bea6545 git-svn: remove some noisy debugging messages
We don't need them anymore, all the rough points of
the --follow-parent implementation have been worked out.

The only improvement in the future will probably be
--follow-parent-harder, which will track subdirectories and
follow individual file history (so annotate/blame can be
complete); but that is still a ways off.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
d542aedb94 git-svn: remove check_path calls before calling do_update
These checks were needed before git-svn got smarter about
match_paths() and using path information returned by get_log().
We also have extra checking against fetching revisions
out-of-order these days; so we don't have to worry about that as
much.  We also check for tree deletions in match_paths() and
skip those as well.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
b9dffd8cad git-svn: --follow-parent tracks multi-parent paths
We can have a branch that was deleted, then re-added under the
same name but copied from another path, in which case we'll have
multiple parents (we don't want to break the original ref, nor
lose copypath info).

Add a test for this, too, of course.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
e518192f3b git-svn: implement auto-discovery of branches/tags
This is similar to the way git proper handles refs, except we
use the keys 'branches' and 'tags' to distinguish when we want
to use wildcards.

The left-hand side of the ':' contains the remote path, and must
have one asterisk ('*') in it for the branch name.  The asterisk
may be in any component of the path as long as is it on its own
directory level.

The right-hand side contains the refname and must have the
asterisk as the last path component.

        branches = branches/*:refs/remotes/*
        tags = tags/*:refs/remotes/tags/*

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
d2ae14346c git-svn: run get_log() on a sub-directory if possible
This is an optimization that should conserve network
bandwidth on certain repositories and configurations.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
fbcc1737d6 git-svn: reintroduce using a single get_log() to fetch
We'll need to rely on path matching to handle wildcard support for branches and
tags.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
4bb9ed0466 git-svn: prepare multi-init for wildcard support
Update the tests since we no longer write so many things to the
config.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
9fa00b655c git-svn: just name the default svn-remote "svn" instead of "git-svn"
It can be confusing and redundant, since historically the
default remote ref (not remote itself) has been "git-svn", too.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
502c1bf629 git-svn: avoid extra get_log calls when refspecs are added for fetching
Since fetch_loop_common starts from the lowest revision number
in a group of Git::SVN objects; we want to avoid refetching
get_log for current users for things we've already cut it.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
ef70de9685 git-svn: get rid of revisions_eq check for --follow-parent
This was originally needed before we used the delta fetcher and
had a less-clean follow-parent implementation that could leave
holes in the history.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
471bc00052 git-svn: migrations default to [svn-remote "git-svn"]
It looks better (like [remote "origin"]) instead of whatever
refname came up first in our directory traversal.  Of course
--remote= overrides this.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
88cf4107eb git-svn: save paths to tags/branches with for future reuse
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
d8115c5104 git-svn: don't write to the config file from --follow-parent
Having 'fetch' entries in the config file created from
--follow-parent is wasteful because it can cause *future* of
invocations to follow revisions we were never interested in
in the first place.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
ce4b4af7ff git-svn: use sys* IO functions for reading rev_db
Using buffered IO for reading 40-41 bytes at a time isn't very
efficient.  Buffering writes for a short duration is alright
since we close() right away and buffers will be flushed.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
9c93fee51e git-svn: avoid redundant get_log calls between invocations
Prefill .rev_db to the maximum revision we tried to fetch;
and take advantage of that so we can avoid using get_log()
on ranges we've already seen (and have deemed uninteresting).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
373274f978 git-svn: do our best to ensure that our ref and rev_db are consistent
Defer any signals that cause termination while they are
updating; and put the update-ref call as close to the rename()
as possible.  Also, make things extra-safe (but slower) for
people using --no-metadata since they can't rely on .rev_db
being rebuilt if it's clobbered (well, I'm calling update-ref
with the -m flag for reflogs, we don't yet have a way to rebuild
.rev_db from reflogs.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
ecc712ddc4 git-svn: re-enable repacking flags
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
47a0b75e01 git-svn: avoid a huge memory spike with high-numbered revisions
Passing very large strings as arguments is bad for memory usage
as it never seems to get freed in Perl.  The .rev_db format is
already not optimized for projects with sparse history.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
d4eff2bda5 git-svn: make (multi-)fetch safer but slower
get_log with explicit paths is the safest way to get revisions
that change a particular path we're interested in.
Unfortunately that means we still have to run get_log multiple
times for each path we're interested in, and even more if
a path gets deleted.

The first argument of get_log() is an array reference, but we
shouldn't use more than one element in that array ref because
the non-existence of _one_ of those paths for a particular range
would cause an error for all paths in that range, so yes, we
need multiple get_log calls to be on the safe side...

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
c7eba7163b git-svn: gracefully handle --follow-parent failures
We don't always know that a path will exist at a particular
revision.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
9760adcccc git-svn: reinstate --no-metadata, add --svn-remote=, variable cleanups
--svn-remote allows the default remote name to be overridden (useful
for tracking multiple SVN repositories).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:11 -08:00
8a603774de git-svn: fix several fetch bugs related to repeated invocations
We no longer delete the top-level directory even if it got
deleted from the upstream repository.  In gs_do_update; we
double-check that the path we're tracking exists at both
endpoints before proceeding.  We have also added additional
protection against fetching revisions out-of-order.

To simplify our internal interfaces, I've disabled passing the
'recursive' flag to the gs_do_{switch,update} wrapper functions
since we always want it in git-svn.  We also pass the
entire Git::SVN object rather than just the path because it
helped me debug.

When printing progress, the refname is printed out to make
it less confusing when multi-fetch is running.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
f0ecca1041 git-svn: remove the 'rebuild' command and make the functionality automatic
Since refs/remotes/* are not automatically cloned, we expect the
user to be capable of copying those references themselves
anyways.

Also removed the documentation for --ignore-nodate while we're
at it; it has also been made automatic.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
289370578c git-svn: fetch tracks initial change with --follow-parent
We were still skipping path information from get_log if we are
tracking /r9270/drunk/subversion/bindings/..., but got something
like this in the log:

   A /r9270/drunk (from /r9270/trunk:14)

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
5d3b7cd5fe git-svn: don't rely on do_switch + reparenting with svn(+ssh)://
I can't seem to figure out what I or the SVN libraries are doing
wrong, but it appears to be related to reparent and probably
some global structure that gets reset if multiple SVN
connections are being used.

So now, in order to use do_switch; we'll open a new connection
to the repository with the complete URL; but we can't seem to
ever use an existing Ra object after another one has been
created...

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
f7c3fc4a26 git-svn: reinstate the default SVN error handler after using get_log
We don't need our own error handler for other operations.  Also
add a message about the successfully do_switch or do_update in
follow-parent for debugging do_switch failures with svn:// and
svn+ssh:// connections.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
90c1b15da3 git-svn: just use Digest::MD5 instead of requiring it
Historically, git-svn did not always use Digest::MD5 because
it did not use the SVN::Delta::Editor interfaces.  Nowadays
it does, and the requires make strace more noisy.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
24e22aa8a5 git-svn: cleanup: move editor-specific variables into the editor namespace
Also removed some unused/redundant functions.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
ce2a0f2f9d git-svn: stop using path names as refnames with --follow-parent
Using path names as refnames breaks horribly if a user is
tracking one large, toplevel directory, and a lower-level
directory is followed from another project is a parent
of another ref, as it will cause refnames such as:
'refs/remotes/trunk/path/to/stuff', which will conflict
with a refname of 'refs/remotes/trunk'.

Now we just append @$revno to the end of it the current
refname.  And if we have followed back to a grandparent, then
we'll strip any existing '@$parent_revno' strings before
appending our own '@$revno' string to it.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
2b27f6c884 git-svn: correctly handle do_{switch,update} in deep directories
The do_update or do_switch functions in SVN only allow for a
single path component; so 'path/to/deep/dir' would be
interpreted as 'path'.

SVN 1.4.x has a reparent function that can let us change the
session to use a higher-level root of the repository, so we can
use that for do_switch (which still doesn't seem to work in SVN
1.4.3 (a fix was attempted, but they missed the rest of the
typemap changes needed in trunk...)).

On the do_update side, we can use set_path on higher level
directories and set them to a newer revision so they don't get
updated.  We can't do this with do_switch, either, because the
relative path we're tracking can change (directory moving into
a child of itself).

Because of these changes, we need to double check that our Fetch
editor is correctly performing stripping on any prefixed paths
from update, otherwise we'll just die() because that would be
a bug.

Added a test case which helped me notice and fix problems with
do_switch, too.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
2fa6a23efb git-svn: correctly track diff-less copies with do_switch
Also, this should allow for the tracking of new, but empty
directories where we would want to see the log message.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
0af9c9f94a git-svn: allow multi-fetch to fetch things chronologically
Since single fetching is a special case of multi-fetch,
share code with it and the fetch loop into Git::SVN::Ra
since it uses a single Ra connection and multiple
Git::SVN objects.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
21819a3708 git-svn: cleanup remove unused function
Also move tz_to_s_offset into Git::SVN::Log since that's
the only place it's used now.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
6139535436 git-svn: simplify usage of the SVN::Git::Editor interface
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
6e8548cca8 git-svn: avoid an extra svn_ra connection during commits
Before, we needed a separate svn_ra instance to run
our check_path calls once the editor was active; but
we can avoid that by running all the check_path calls
before our editor is active.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
d3a840dc74 git-svn: fix committing to subdirectories, add tests
I broke this part with the URL minimization; since
git-svn will now try to connect to the root of
the repository and will end up writing files
there if it can...

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
3ebe8df7f6 git-svn: fix segfaults from accessing svn_log_changed_path_t
svn_log_changed_path_t structs were being used out of scope
outside of svn_ra_get_log (because I wanted to eventually be
able to use git-svn with only a single connection to the
repository).  So now we dup them into a hash.

This was fixed while making --follow-parent fetches more
efficient.  I've moved parsing of the command-line --revision
argument outside of the Git::SVN module so Git::SVN::fetch() can
be used in more places (such as find_parent_branch).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
e5a0b240fc git-svn: correctly track revisions made to deleted branches
git-svn has never been able to handle deleted branches very well
because svn_ra_get_log() is all-or-nothing, meaning that if the
max revision passed to it does not contain the path we're
tracking, we miss all the revisions in the repository.

Branches fetched using --follow-parent still do this
sub-optimally (will be fixed soon).  --follow-parent will soon
become the default, so we will assume that when using get_log();

We will also avoid tracking revprops for revisions with no
path-related changes since otherwise we just end up pulling
logs to paths we don't care about.

Also added a test for this to t9104-git-svn-follow-parent.sh and
correctly commit the log message in the preceeding test (which
conflicted with a filename).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
97f6987afa git-svn: avoid tracking change-less revisions
They simply aren't interesting to track, and this will allow
us to avoid get_log().

Since r0 is covered by this, we need to update the tests to not
rely on r0 (which is always empty).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
1492b4245a git-svn: add an odd test case that seems to cause segfaults over HTTP
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
ef3cfaad19 git-svn: track writes writes to the index in fetch
Introducing Git::IndexInfo.  This module will probably be useful
outside of git-svn, so I'm not putting it in the Git::SVN
namespace.

This will allow me to more easily avoid the use of get_log() in
the future and simply run do_update in incrementing ranges.
get_log() should be avoided because there are cases where
moved/deleted directories do not track correctly (until
--follow-parent is run on a new branch).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
7f578c55af git-svn: --follow-parent now works on sub-directories of larger branches
This means that tracking the path of:

  /another-larger/trunk/thunk/bump/thud inside a repository

would follow:

  /larger-parent/trunk/thunk/bump/thud

even if the svn log output looks like this:
  --------------------------------------------
  Changed paths:
     A /another-larger (from /larger-parent:5)
  --------------------------------------------

Note: the usage of get_log() in git-svn still makes a
an assumption that shouldn't be made with regard to
revisions existing for a particular path.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:10 -08:00
e6434f8760 git-svn: 'init' attempts to connect to the repository root if possible
This allows connections to be used more efficiently and not require
users to run 'git-svn migrate --minimize' for new repositories.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
9bf046372b git-svn: better error reporting if --follow-parent fails
This will be useful to me when I try more special-cases
of parent-tracking.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
536c4b0937 git-svn: allow 'init' to work outside of tests
Tests always ran 'git init' before we ran so that repo-config
would always have something to read.  However that does not work
in real-world situations where the user expects 'git svn init'
to work without running 'git init' first.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
07a1c95045 git-svn: get rid of additional fetch-arguments
It's not really useful anymore now that we have a better
--follow-parent for the valid cases.  Any other use
of it is not valid.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
a2003abc23 git-svn: allow --follow-parent on deleted directories
Any operations on the index in Git::SVN that is not wrapped by
tmp_index_do() is wrong.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
b805b44a92 git-svn: disallow ambigious local refspecs
Having multiple fetch refspecs pointing to the same local ref
would be a very bad thing.  Start avoiding the use of fatal() or
exit() inside the modules so we can libify more easily.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
8b8fc06824 git-svn: --follow-parent works with svn-remotes multiple branches
Bugs fixed:

 * We didn't allow manually (not using git-svn) init-ed
   remotes/fetch refspecs to be used before.  It works now
   because that's what I did in this test.  git-svn init should
   offer more control in the future.
 * correctly strip paths in the delta editor when using
   do_switch().
 * Make the -i / GIT_SVN_ID option work correctly when doing
   fetch on a multi-ref svn-remote

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
15710b6f34 git-svn: fix --follow-parent to work with Git::SVN
While we're at it, beef up the test because I was
getting false-passes during development.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
47e39c55c9 git-svn: enable --minimize to simplify the config and connections
--minimize will update the git-svn configuration to attempt to
connect to the repository root (instead of directly to the
path(s) we are tracking) in order to allow more efficient reuse
of connections (for multi-fetch and follow-parent).

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
f6f0987646 git-svn: reuse open SVN::Ra connections by URL
Note: this can cause problems with Perl's reference counting GC,
so I'm disabling Git::SVN::Ra::DESTROY.  If we notice more
problems down the line, we can disable this enhancement.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
780a2f58e7 git-svn: fix a regression in dcommit that caused empty log messages
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
706587fc6d git-svn: add support for metadata in .git/config
Of course, we handle metadata migrations from previous versions
and we have added unit tests.

The new .git/config remotes resemble non-SVN remotes.  Below
is an example with comments:

[svn-remote "git-svn"]
	; like non-svn remotes, we have one URL per-remote
	url = http://foo.bar.org/svn

	; 'fetch' keys are done in the same way as non-svn
	; remotes, too.  With the left-hand-side of the ':'
	; being the remote (SVN) repository path relative to the
	; above 'url' key; and the right-hand-side being a
	; remote ref in git (refs/remotes/*).
	; An empty left-hand-side means that it will fetch
	; the entire contents of the 'url' key.
	; old-style (migrated from previous versions of git-svn)
	; are like this:
	fetch = :refs/remotes/git-svn

	; this is created by a current version of git-svn
	; using the multi-init command with an explicit
	; url (specified above).  This allows multi-init
	; to reuse SVN::Ra connections.
	fetch = trunk:refs/remotes/trunk
	fetch = branches/a:refs/remotes/a
	fetch = branches/b:refs/remotes/b
	fetch = tags/0.1:refs/remotes/tags/0.1
	fetch = tags/0.2:refs/remotes/tags/0.2
	fetch = tags/0.3:refs/remotes/tags/0.3

[svn-remote "alt"]
	; this is another old-style remote migrated over
	; to the new config format
	url = http://foo.bar.org/alt
	fetch = :refs/remotes/alt

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
d05d72e07e git-svn: remove graft-branches command
It's becoming a maintenance burden.  I've never found it
particularly useful myself, nor have I heard much feedback about
it; so I'm assuming it's just as useless to everyone else.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
1ce255dc16 git-svn: convert 'set-tree' command to use Git::SVN
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
d7ad3bed8c git-svn: switch dcommit to using Git::SVN code
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
1c8443b050 git-svn: fetch/multi-fetch converted over to Git::SVN module
--follow-parent and commit-diff are currently broken with
this commit...

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
396988e0b9 git-svn: get rid of Memoize for now...
I may refactor more of this stuff into separate modules
2007-02-23 00:57:09 -08:00
44320b9e0e git-svn: convert the 'commit-diff' command to Git::SVN
Also, convert all usage of 'log_msg' to 'log_entry' for
consistency's sake

SVN::Git::Editor::apply_diff now drives the rest of the
editor.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
c843c464b8 git-svn: do not let Git.pm warn if we prematurely close pipes
This mainly quiets down warnings when running git svn log.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
e7f023c81a git-svn: port the 'rebuild' command to use Git::SVN objects
Also correctly shared some variables needed for Git::SVN::Log

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
f8c9d1d27f git-svn: moved the 'log' command into its own namespace
More cleanup to separate out functionality and make things
nicer to hack on.

While we're at it, centralize loading of the authors into
one place and correctly handle '(no author)' cases in
when showing logs after-the-fact; and not just at commit
time.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
5969cbe13c git-svn: convert show-ignore over to Git::SVN
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:09 -08:00
ad2f90851e git-svn: add a test for show-ignore
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
e7db67e6f1 git-svn: make multi-init capable of reusing the Ra connection
If a user specified a seperate URL and --tags/--branches as
a sepearte URL, allow the Ra object (and therefore the connection)
to be reused.

We'll get rid of libsvn_ls_fullurl() since it was only used
in one place.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
8164b6525e git-svn: convert multi-init over to using Git::SVN
Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
d2866f9e1f git-svn: convert 'init' to use Git::SVN
While we're at it, fix up some bugs in Git::SVN.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
9b981fc659 git-svn: add Git::SVN module (to avoid global variables)
This should make it easier to improve multi-fetch and
--follow-parent by avoiding global variables.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
336f1714ae git-svn: cleanup: avoid re-use()ing Git.pm in sub-packages
I will be using functions from Git.pm in more modules, so I
want to avoid re-importing the long argument list everywhere
it's used.

Also removed an unused command-line switch
(--no-ignore-externals) and some variables.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
d81bf82719 git-svn: cleanup: put SVN workarounds into their own namespace
Force some svn_ra functions to use a temporary pool via wrapper

This cleans up the code a bit by removing explicit instances of
pool allocation and deallocation and providing wrapper functions
that make use of temporary pools.

I've also added an explicit pool usage when creating the commit
editor for commit-diff where get_commit_editor can be called
multiple times with the same pool previously.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
4a87db0e12 git-svn: cleanup: move process_rm around
(it's only used in one function now)

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
d976acfd89 git-svn: move authentication prompts into their own namespace
I'm going to be reorganizing some more code.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
2007-02-23 00:57:08 -08:00
239296770d git-bundle: record commit summary in the prerequisite data 2007-02-22 22:30:33 -08:00
3d1efd8f1d git-bundle: fix 'create --all' 2007-02-22 22:30:33 -08:00
fb9a54150d git-bundle: avoid fork() in verify_bundle()
We can use the revision walker easily for checking if the
prerequisites are met, instead of fork()ing off a rev-list,
which would list only the first unmet prerequisite.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 22:30:33 -08:00
fa257b0554 git-bundle: assorted fixes
This patch fixes issues mentioned by Junio, Nico and Simon:

- I forgot to convert the usage string when removing the "--" from
  the subcommands,
- a style fix in the bundle_header,
- use xread() instead of read(),
- use write_or_die() instead of write(),
- make the bundle header extensible,
- fail if the whitespace after a sha1 of a reference is missing,
- close() the fds passed to a subprocess,
- in verify_bundle(), do not use "rev-list --stdin", but rather
  pass the revs directly (avoiding a fork()),
- fix a corrupted comment in show_object(), and
- fix the size check in index_pack.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 22:30:33 -08:00
2e0afafebd Add git-bundle: move objects and references by archive
Some workflows require use of repositories on machines that cannot be
connected, preventing use of git-fetch / git-push to transport objects and
references between the repositories.

git-bundle provides an alternate transport mechanism, effectively allowing
git-fetch and git-pull to operate using sneakernet transport. `git-bundle
create` allows the user to create a bundle containing one or more branches
or tags, but with specified basis assumed to exist on the target
repository. At the receiving end, git-bundle acts like git-fetch-pack,
allowing the user to invoke git-fetch or git-pull using the bundle file as
the URL. git-fetch and git-ls-remote determine they have a bundle URL by
checking that the URL points to a file, but are otherwise unchanged in
operation with bundles.

The original patch was done by Mark Levedahl <mdl123@verizon.net>.

It was updated to make git-bundle a builtin, and get rid of the tar
format: now, the first line is supposed to say "# v2 git bundle", the next
lines either contain a prerequisite ("-" followed by the hash of the
needed commit), or a ref (the hash of a commit, followed by the name of
the ref), and finally the pack. As a result, the bundle argument can be
"-" now.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 22:30:33 -08:00
8565d2d853 Make tests independent of global config files
This was done by setting $HOME to somewhere bogus. A better method is
to reuse $GIT_CONFIG, which was invented for ignoring the global
config file explicitely.

Technically, setting GIT_CONFIG=.git/config could be wrong, but it
passes all the tests, and we can keep the tests that way.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 22:06:26 -08:00
ef1a5c2fa8 Merge branches 'lt/crlf' and 'jc/apply-config'
* lt/crlf:
  Teach core.autocrlf to 'git apply'
  t0020: add test for auto-crlf
  Make AutoCRLF ternary variable.
  Lazy man's auto-CRLF

* jc/apply-config:
  t4119: test autocomputing -p<n> for traditional diff input.
  git-apply: guess correct -p<n> value for non-git patches.
  git-apply: notice "diff --git" patch again
  Fix botched "leak fix"
  t4119: add test for traditional patch and different p_value
  apply: fix memory leak in prefix_one()
  git-apply: require -p<n> when working in a subdirectory.
  git-apply: do not lose cwd when run from a subdirectory.
  Teach 'git apply' to look at $HOME/.gitconfig even outside of a repository
  Teach 'git apply' to look at $GIT_DIR/config
2007-02-22 21:34:36 -08:00
e79cbbea9e Merge branch 'maint'
* maint:
  git-diff: fix combined diff
  Fix 'git commit -a' in a newly initialized repository
  Include git-gui credits file in dist.
  Document the new core.bare configuration option.
2007-02-22 21:27:37 -08:00
e52a5de45a pretty-formats: add 'format:<string>'
With this patch,

$ git show -s \
	--pretty=format:'  Ze komit %h woss%n  dunn buy ze great %an'

shows something like

  Ze komit 04c5c88 woss
  dunn buy ze great Junio C Hamano

The supported placeholders are:

	'%H': commit hash
	'%h': abbreviated commit hash
	'%T': tree hash
	'%t': abbreviated tree hash
	'%P': parent hashes
	'%p': abbreviated parent hashes
	'%an': author name
	'%ae': author email
	'%ad': author date
	'%aD': author date, RFC2822 style
	'%ar': author date, relative
	'%at': author date, UNIX timestamp
	'%cn': committer name
	'%ce': committer email
	'%cd': committer date
	'%cD': committer date, RFC2822 style
	'%cr': committer date, relative
	'%ct': committer date, UNIX timestamp
	'%e': encoding
	'%s': subject
	'%b': body
	'%Cred': switch color to red
	'%Cgreen': switch color to green
	'%Cblue': switch color to blue
	'%Creset': reset color
	'%n': newline

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 21:03:41 -08:00
d516c2d119 Teach git-diff-files the new option --no-index
With this flag and given two paths, git-diff-files behaves as a GNU diff
lookalike (plus the git goodies like --check, colour, etc.).  This flag
is also available in git-diff.  It also works outside of a git repository.

In addition, if git-diff{,-files} is called without revision or stage
parameter, and with exactly two paths at least one of which is not tracked,
the default is --no-index.

So, you can now say

	git diff /etc/inittab /etc/fstab

and it actually works!

This also unifies the duplicated argument parsing between cmd_diff_files()
and builtin_diff_files().

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 20:59:55 -08:00
aeabfa0725 apply: make --verbose a little more useful
When a patch fails, I automatically add '-v' to the command line
to see what fails.

This patch makes -v a synonym to --verbose, and actually tells
the user which text was not found.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 20:58:36 -08:00
b4e1e4a787 run_diff_{files,index}(): update calling convention.
They used to open and read index themselves, but they now expect
their callers to do so.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 02:02:15 -08:00
7b802b86a6 update-index: do not die too early in a read-only repository.
This delays the error exit from hold_lock_file_for_update() in
update-index, so that "update-index --refresh" in a read-only
repository can still report what paths are stat-dirty before
exiting.

Also it makes -q to squelch the error message.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 00:31:53 -08:00
2b5f9a8c0c git-status: do not be totally useless in a read-only repository.
This makes git-status work semi-decently in a read-only
repository.  Earlier, the command simply died with "cannot lock
the index file" before giving any useful information to the
user.

Because index won't be updated in a read-only repository,
stat-dirty paths appear in the "Changed but not updated" list.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-22 00:31:51 -08:00
fe6e0eecb0 t4119: test autocomputing -p<n> for traditional diff input.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-21 16:18:45 -08:00
3e8a5db966 git-apply: guess correct -p<n> value for non-git patches.
This enhances the third point in the previous commit.  When
applying a non-git patch that begins like this:

	--- 2.6.orig/mm/slab.c
	+++ 2.6/mm/slab.c
	@@ -N,M +L,K @@@
	...

and if you are in 'mm' subdirectory, we notice that -p2 is the
right option to use to apply the patch in file slab.c in the
current directory (i.e. mm/slab.c)

The guess function also knows about this pattern, where you
would need to use -p0 if applying from the top-level:

	--- mm/slab.c
	+++ mm/slab.c
	@@ -N,M +L,K @@@
	...

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-21 16:05:56 -08:00
9987d7c58a git-apply: notice "diff --git" patch again
Earlier one that tried to be too consistent with GNU patch by
not stripping the leading path when we _know_ we are in a
subdirectory and the patch is relative to the toplevel was a
mistake.  This fixes it.

 - No change to behaviour when it is run from the toplevel of
   the repository.

 - When run from a subdirectory to apply a git-generated patch,
   it uses the right -p<n> value automatically, with or without
   --index nor --cached option.

 - When run from a subdirectory to apply a randomly generated
   patch, it wants the right -p<n> value to be given by the
   user.

The second one is a pure improvement to correct inconsistency
between --index and non --index case, compared with 1.5.0.  The
third point could be further improved to guess what the right
value for -p<n> should be by looking at the patch, but should be
a topic of a separate patch.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-21 14:42:15 -08:00
2470653196 Merge branch 'maint'
* maint:
  Use gunzip -c over gzcat in import-tars example.
  git-gui: Don't crash in citool mode on initial commit.
  git-gui: Remove TODO list.
  git-gui: Include browser in our usage message.
  git-gui: Change summary of git-gui.
  git-gui: Display all authors of git-gui.
  git-gui: Use mixed path for docs on Cygwin.
  git-gui: Correct crash when saving options in blame mode.
  git-gui: Expose the browser as a subcommand.
  git-gui: Create new branches from a tag.
  git-gui: Prefer version file over git-describe.
  git-gui: Print version on the console.
  git-gui: More consistently display the application name.
  git-gui: Permit merging tags into the current branch.
  git-gui: Basic version check to ensure git 1.5.0 or later is used.
  git-gui: Refactor 'exec git subcmd' idiom.
2007-02-21 11:16:20 -08:00
6c912f5b04 Fix botched "leak fix"
When (new_name == old_name), the previous one prefixed old_name
alone, leaving new_name untouched, and worse yet, left it
dangling pointing at an already freed memory location.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-21 01:14:34 -08:00
c24e9757e9 t4119: add test for traditional patch and different p_value
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-21 01:14:22 -08:00
b5a40a5724 git-remote: support remotes with a dot in the name
[jc: the original from Pavel was limiting the variable names to only
 fetch and url, but I loosened it to take valid variable names.]

Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-21 00:07:24 -08:00
13e36ec51b Teach diff -B about colours
Matthias Lederhofer noticed that `diff -B` did not pick up on diff
colournig.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-21 00:03:37 -08:00
1918278ea1 Allow git-remote to update named groups of remotes
In response to a feature request from Shawn Pearce, this patch allows
a user to update a named group of remotes by using "git remote update
<group>", where the group is defined in the config file by
remotes.<group>.  The default if the named group is not specified is
now fetched group remotes.default, instead of remote.fetch, which is
what had been previously used.

In addition, if remotes.default is not defined, all remotes defined in
the config file will be used, as before, but there is now also
possible to request that a particular repository to be skipped by
default by using the boolean configuration parameter
remote.<name>.skipDefaultUpdate.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 23:58:39 -08:00
7b9a13ece8 Add config_boolean() method to the Git perl module
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 23:58:37 -08:00
4a6b9bb60a Allow passing of an alternative CVSROOT via -d.
This is necessary if using CVS in an asymmetric fashion, i.e. when the
CVSROOT you are checking out from differs from the CVSROOT you have to
commit to.

Signed-off-by: Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 23:58:27 -08:00
d2cd696322 disable t4016-diff-quote.sh on some filesystems
... because the filesystems (most typically FAT and NTFS) do not support
HT nor LF in filenames.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
2007-02-20 23:55:22 -08:00
b97e911643 Support for large files on 32bit systems.
Glibc uses the same size for int and off_t by default.
In order to support large pack sizes (>2GB) we force Glibc to a 64bit off_t.

Signed-off-by: Martin Waitz <tali@admingilde.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 22:45:09 -08:00
34c6a82b8a git grep: use pager
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 22:44:35 -08:00
4b22f634a3 Merge branch 'fk/autoconf'
* fk/autoconf:
  New autoconf test for iconv
2007-02-20 22:28:22 -08:00
5ead60e619 Merge branch 'js/name-rev-fix'
* js/name-rev-fix:
  name-rev: avoid "^0" when unneeded
2007-02-20 22:24:03 -08:00
1968d77dd6 prefixcmp(): fix-up leftover strncmp().
There were instances of strncmp() that were formatted improperly
(e.g. whitespace around parameter before closing parenthesis)
that caused the earlier mechanical conversion step to miss
them.  This step cleans them up.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 22:03:15 -08:00
599065a3bb prefixcmp(): fix-up mechanical conversion.
Previous step converted use of strncmp() with literal string
mechanically even when the result is only used as a boolean:

    if (!strncmp("foo", arg, 3)) ==> if (!(-prefixcmp(arg, "foo")))

This step manually cleans them up to read:

    if (!prefixcmp(arg, "foo"))

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 22:03:15 -08:00
cc44c7655f Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily.  Leftover from this will be fixed in a separate step, including
idiotic conversions like

    if (!strncmp("foo", arg, 3))

  =>

    if (!(-prefixcmp(arg, "foo")))

This was done by using this script in px.perl

   #!/usr/bin/perl -i.bak -p
   if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
           s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
   }
   if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
           s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
   }

and running:

   $ git grep -l strncmp -- '*.c' | xargs perl px.perl

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 22:03:15 -08:00
cff0302c14 Add prefixcmp()
We have too many strncmp(a, b, strlen(b)).

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 22:03:14 -08:00
9360f27ff7 Merge branch 'maint'
* maint:
  Check for PRIuMAX rather than NO_C99_FORMAT in fast-import.c.
2007-02-20 22:02:15 -08:00
a53b12c3a2 Link 1.5.0.1 documentation from the main page.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 00:44:35 -08:00
32043c9f8c config: read system-wide defaults from /etc/gitconfig
The settings in /etc/gitconfig can be overridden in ~/.gitconfig,
which in turn can be overridden in .git/config.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 23:05:16 -08:00
83a5ad6126 fetch & clone: do not output progress when not on a tty
This adds the option "--no-progress" to fetch-pack and upload-pack,
and makes fetch and clone pass this option when stdout is not a tty.

While at documenting that option, also document --strict and --timeout
options for upload-pack.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 19:20:05 -08:00
c4025103fa rev-list --max-age, --max-count: support --boundary
Now, when saying --max-age=<timestamp>, or --max-count=<n>, together
with --boundary, rev-list prints the boundary commits, i.e. the
commits which are _just_ not shown without --boundary, i.e. their
children are, but they aren't.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 19:07:01 -08:00
59d3f541cf name-rev: avoid "^0" when unneeded
When naming by a tag, we used to add "^0" even if this was not really
necessary. For example, `git name-rev de6f0def` now outputs

	de6f0def tags/v1.5.0.1~9

instead of

	de6f0def tags/v1.5.0.1^0~9

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 19:03:59 -08:00
eac70c4f64 apply: fix memory leak in prefix_one()
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 19:02:12 -08:00
56185f49d0 git-apply: require -p<n> when working in a subdirectory.
git-apply running inside a subdirectory, with or without --index,
used to always assume that the patch is formatted in such a way
to apply with -p1 from the toplevel, but it is more useful and
consistent with the use of "GNU patch -p1" if it defaulted to
assume that its input is meant to apply at the level it is
invoked in.

This changes the behaviour.  It used to be that the patch
generated this way would apply without any trick:

	edit Documentation/Makefile
	git diff >patch.file
	cd Documentation
	git apply ../patch.file

You need to give an explicit -p2 to git-apply now.  On the other
hand, if you got a patch from somebody else who did not follow
"patch is to apply from the top with -p1" convention, the input
patch would start with:

	diff -u Makefile.old Makefile
	--- Makefile.old
	+++ Makefile

and in such a case, you can apply it with:

	git apply -p0 patch.file

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 18:44:59 -08:00
aea1945744 git-apply: do not lose cwd when run from a subdirectory.
When a patch modifies (not deletes) the last file in a
directory, because we treat a modification just as deletion
followed by creation, and deleting the last file in a directory
automatically rmdir(2)'s that directory, we ended up removing
the directory, which can potentially be the cwd, and then
recreating the same directory to create the patch result.

Avoid the rmdir step when remove_file() is called only because
we are replacing it with the result by later calling
create_file().

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 18:44:21 -08:00
1e592d65b5 Teach git-remote to update existing remotes by fetching from them
This allows users to use the command "git remote update" to update all
remotes that are being tracked in the repository.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-19 18:34:33 -08:00
0bce7a52f2 Merge branch 'js/diff-color-check'
* js/diff-color-check:
  diff --check: use colour
2007-02-19 18:30:59 -08:00
50cfde1453 Merge branch 'jc/fetch-notags'
* jc/fetch-notags:
  remotes.not-origin.tagopt
2007-02-19 18:30:52 -08:00
2b2b892e36 Merge branch 'maint'
* maint:
  Obey NO_C99_FORMAT in fast-import.c.
  Add a compat/strtoumax.c for Solaris 8.
  git-clone: Sync documentation to usage note.
2007-02-19 18:29:41 -08:00
7e53607c95 Merge branch 'ap/cvsserver'
* ap/cvsserver:
  Have git-cvsserver call hooks/update before really altering the ref

Acked-by: Martin Langhoff <martin@catalyst.net.nz>
2007-02-19 13:12:39 -08:00
f5a9264769 Merge branch 'maint'
* maint:
  GIT 1.5.0.1
  Documentation/i18n.txt: it is i18n.commitencoding not core.commitencoding
  Read the config in rev-list

Conflicts:

	RelNotes
2007-02-18 18:45:52 -08:00
e63ccb84e3 New autoconf test for iconv
On a Solaris machine I have access to libc contains the symbol
"iconv" but, when compiling with gcc and including iconv.h we get
iconv.h from GNU libiconv. This header file define (among other
things) "iconv" to "libiconv" and so on.

In order to link with GNU libiconv we need -liconv. Currently we
test if the symbol "iconv" is in libc (which is true), then we get
a undefined reference error because we don't have libiconv_open.

The solution this patch implements is to compile and link a
small test program, instead of just checking if the libraries
(libc and libiconv) contains the symbol "iconv".

Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-18 15:57:36 -08:00
c5a8c3ecd7 diff --check: use colour
Reuse the colour handling of the regular diff.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-18 15:45:51 -08:00
700ea47936 Teach 'git apply' to look at $HOME/.gitconfig even outside of a repository
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-18 00:54:04 -08:00
b758120144 Update draft release notes for 1.5.1
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-17 16:18:14 -08:00
69bc0e22d3 Merge branch 'maint'
* maint:
  Update draft release notes for 1.5.0.1
  Convert update-index references in docs to add.
  Attempt to improve git-rebase lead-in description.
  Do not take mode bits from index after type change.
  git-blame: prevent argument parsing segfault
  Make gitk save and restore window pane position on Linux and Cygwin.
  Make gitk save and restore the user set window position.
  [PATCH] gitk: Use show-ref instead of ls-remote
  [PATCH] Make gitk work reasonably well on Cygwin.
  [PATCH] gitk - remove trailing whitespace from a few lines.
  Change git repo-config to git config
2007-02-17 16:16:48 -08:00
6716027108 Teach core.autocrlf to 'git apply'
This teaches git-apply that the data read from and written to
the filesystem might need to get converted to adjust for local
line-ending convention.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-17 15:27:47 -08:00
dc7b24364d Teach 'git apply' to look at $GIT_DIR/config
When neither --index nor --cached was used, git-apply did not
try calling setup_git_directory(), which means it did not look
at configuration files at all.  This fixes it to call the setup
function but still allow the command to be run in a directory
not controlled by git.

The bug probably meant that 'git apply', not moving up to the
toplevel, did not apply properly formatted diffs from the
toplevel when you are inside a subdirectory, even though 'git
apply --index' would.  As a side effect, this patch fixes it as
well.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-17 13:13:32 -08:00
2afc29aa84 name-rev: introduce the --refs=<pattern> option
Instead of (or, in addition to) --tags, to use only tags for naming,
you can now use --refs=<pattern> to specify a shell glob pattern
which the refs must match to be used for naming.

Example:

	$ git name-rev --refs=*v1* 33db5f4d
	33db5f4d tags/v1.0rc1^0~1593

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-17 11:26:49 -08:00
53756f290b Merge branch 'maint'
* maint:
  git-merge: minor fix for no_trivial_merge_strategies.
2007-02-16 15:08:46 -08:00
af99711cd8 Merge branch 'maint'
* maint:
  pretend-sha1: grave bugfix.
2007-02-15 17:13:15 -08:00
24424fc2f7 remotes.not-origin.tagopt
With a configuration entry like this:

	[remote "alt-git"]
        	url = git://repo.or.cz/alt.git/git/
                fetch = +refs/heads/*:refs/remotes/alt-git/*
                tagopt = --no-tags

you do not have to say "git pull --no-tags alt-git".  Just
saying "git pull alt-git" would suffice.

Obviously, if you want to get the tag from such an alternate
remote in a separate namespace, you could also do something like:

	[remote "alt-git"]
        	url = git://repo.or.cz/alt.git/git/
                fetch = +refs/heads/*:refs/remotes/alt-git/*
                fetch = +refs/tags/*:refs/remote-tags/alt-git/*
                tagopt = --no-tags

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-15 01:52:14 -08:00
78e90f89e3 Merge branch 'maint'
* maint:
  GIT-VERSION-FILE: check ./version first.
  sha1_file.c: Round the mmap offset to half the window size.
  Make sure packedgitwindowsize is multiple of (pagesize * 2)
  Add RelNotes 1.5.0.1
  Still updating 1.5.0 release notes.
  git-daemon: Avoid leaking the listening sockets into child processes.
  Clarify two backward incompatible repository options.
2007-02-14 15:25:53 -08:00
634ede32ae t0020: add test for auto-crlf
This tests lowlevel of update/checkout codepaths and some patch
application.  Currently, variants of "git apply" that look at
the working tree files does not work, so it does not test the
patch application without parameter and with --index parameter
when autocrlf is set to produce CRLF files.

We should add test for diff generation too.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 14:54:00 -08:00
d7f4633405 Make AutoCRLF ternary variable.
This allows you to do:

	[core]
		AutoCRLF = input

and it should do only the CRLF->LF translation (ie it simplifies CRLF only
when reading working tree files, but when checking out files, it leaves
the LF alone, and doesn't turn it into a CRLF).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 11:19:28 -08:00
6c510bee20 Lazy man's auto-CRLF
It currently does NOT know about file attributes, so it does its
conversion purely based on content. Maybe that is more in the "git
philosophy" anyway, since content is king, but I think we should try to do
the file attributes to turn it off on demand.

Anyway, BY DEFAULT it is off regardless, because it requires a

	[core]
		AutoCRLF = true

in your config file to be enabled. We could make that the default for
Windows, of course, the same way we do some other things (filemode etc).

But you can actually enable it on UNIX, and it will cause:

 - "git update-index" will write blobs without CRLF
 - "git diff" will diff working tree files without CRLF
 - "git checkout" will write files to the working tree _with_ CRLF

and things work fine.

Funnily, it actually shows an odd file in git itself:

	git clone -n git test-crlf
	cd test-crlf
	git config core.autocrlf true
	git checkout
	git diff

shows a diff for "Documentation/docbook-xsl.css". Why? Because we have
actually checked in that file *with* CRLF! So when "core.autocrlf" is
true, we'll always generate a *different* hash for it in the index,
because the index hash will be for the content _without_ CRLF.

Is this complete? I dunno. It seems to work for me. It doesn't use the
filename at all right now, and that's probably a deficiency (we could
certainly make the "is_binary()" heuristics also take standard filename
heuristics into account).

I don't pass in the filename at all for the "index_fd()" case
(git-update-index), so that would need to be passed around, but this
actually works fine.

NOTE NOTE NOTE! The "is_binary()" heuristics are totally made-up by yours
truly. I will not guarantee that they work at all reasonable. Caveat
emptor. But it _is_ simple, and it _is_ safe, since it's all off by
default.

The patch is pretty simple - the biggest part is the new "convert.c" file,
but even that is really just basic stuff that anybody can write in
"Teaching C 101" as a final project for their first class in programming.
Not to say that it's bug-free, of course - but at least we're not talking
about rocket surgery here.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 11:19:22 -08:00
9a894e8e7c The "table-of-contents" in the update hook script should match the body
44478d99ee introduced a filter using "git-rev-parse --not --all" to the
log display to prevent the display of revisions already in the
repository.  However, the table of contents generation didn't get that
same update.

This patch fixes that.  The table of contents before the log and the log
now both display the same list of revisions.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 10:14:26 -08:00
b2741f63d4 Have git-cvsserver call hooks/update before really altering the ref
git-cvsserver is analogous to git-receive-pack; a checking from a cvs
client to a central server is like a git-push from a working repository.
Therefore it's nice to use the same access control (and email sending)
that a receive-pack would perform.

This patch tests for an executable update hook; if it is it is run with
the ref being updated and the old and new hashes as normal.  If the
update hook returns an error code the update is aborted and the ref is
never updated.  The cvsserver returns "error 1" to the client to signal
there was an EPERM error.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 02:15:42 -08:00
f5d43056a1 Point top-level RelNotes link at 1.5.1 release notes being prepared.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 00:49:06 -08:00
6fc6668625 Add RelNotes 1.5.1
Instead of running around listing the changes near the release,
let's keep things nicely organized by summarizing the changes as
we merge things to the 'master' branch.

I haven't decided how well this will go with people's patch
submission procedure yet --- we'll play it by the ear and see
what happens.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 00:46:52 -08:00
a44a0c9966 Document --ignore-space-at-eol option.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-14 00:41:32 -08:00
ddfff26651 Merge branch 'maint'
* maint:
  Makefile: update check-docs target
  cmd-list: add git-remote
  Documentation: Drop full-stop from git-fast-import title.
  Minor corrections to release notes
2007-02-13 22:48:32 -08:00
617669da4f Use stdin reflist passing in git-fetch.sh
Use the new stdin reflist passing mechanism for the call to
fetch--tool parse-reflist, allowing passing of more than ~128K
of reflist data.

Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:53 -08:00
95339912b9 Use stdin reflist passing in parse-remote
Use the new stdin reflist passing mechanism for the call to
fetch--tool expand-refs-wildcard, allowing passing of more
than ~128K of reflist data.

Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:53 -08:00
46ce8b6d2a Allow fetch--tool to read from stdin
If the reflist is "-" then read the reflist data from stdin instead,
this will allow the passing of more than 128K of reflist data - which
won't fit in the environment passed by execve.

Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:53 -08:00
86551586da git-fetch: rewrite expand_ref_wildcard in C
This does not seem to make measurable improvement when dealing
with 1000 unpacked refs, but we would need something like it
if we were to do a full rewrite in C somedaoy.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:53 -08:00
d1e0ef6cc8 git-fetch: rewrite another shell loop in C
Move another shell loop that canonicalizes the list of refs for
underlying git-fetch-pack and fetch-native-store into C.

This seems to shave the runtime for the same 1000 branch
repository from 30 seconds down to 15 seconds (it used to be 2
and half minutes with the original version).

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:53 -08:00
fbe2687eba git-fetch: move more code into C.
This adds "native-store" subcommand to git-fetch--tool to
move a huge loop implemented in shell into C.  This shaves about
70% of the runtime to fetch and update 1000 tracking branches
with a single fetch.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:53 -08:00
d4289fff87 git-fetch--tool: start rewriting parts of git-fetch in C.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:52 -08:00
b74e8cbd80 git-fetch: split fetch_main into fetch_dumb and fetch_native
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:43:52 -08:00
859f9c4581 teach diff machinery about --ignore-space-at-eol
`git diff --ignore-space-at-eol` will ignore whitespace at the
line ends.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:40:42 -08:00
44478d99ee Only show log entries for new revisions in hooks--update
If you were issuing emails for two branches, and one merged the other,
you would get the same log messages appearing in two separate emails.

e.g. A working repository, where the last push to central was done at
     the revision marked "B", after which two branches were developed
     further.

  * -- B -- 1 -- 1 -- M (branch1)
        \           /
         2 -- 2 -- 2 (branch2)

Now imagine that branch2 is pushed to the email-generating repository;
an email containing all the "2" revisions would be sent.  Now, let's say
branch1 is pushed, the old update hook would run

 git-rev-list $newrev ^$baserev

Where $newrev would be "M" and $baserev would be "B".  This list
includes all the "2" revisions as well as all the "1" revisions.

This patch addresses this problem by using

 git-rev-parse --not --all | git-rev-list --stdin $newrev ^$baserev

To inhibit the display of all revisions that are already in the
repository.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 21:40:24 -08:00
870b39c15f blame: --show-stats for easier optimization work.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 19:30:03 -08:00
c230390b47 Merge branch 'js/reverse'
* js/reverse:
  Teach revision machinery about --reverse
2007-02-13 19:20:06 -08:00
3eee9c6dbe Merge branch 'jc/diff-apply-patch'
* jc/diff-apply-patch:
  git-diff/git-apply: make diff output a bit friendlier to GNU patch (part 2)
2007-02-13 19:18:16 -08:00
4a164d48df Merge branch 'jc/merge-base' (early part)
This contains an evil merge to fast-import, in order to
resolve in_merge_bases() update.
2007-02-13 16:54:35 -08:00
f8f2aaa172 Merge branch 'jc/deprecate'
As previously announced, diff-stages and resolve are now gone.
2007-02-13 16:45:40 -08:00
6132bd5cac Add link to v1.5.0 documentation.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-13 16:43:24 -08:00
4cc41a16c1 Remove git-diff-stages.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-12 19:33:03 -08:00
207dfa0791 Remove git-resolve.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-12 19:33:03 -08:00
9c5e66e97d Teach revision machinery about --reverse
The option --reverse reverses the order of the commits.

[jc: with comments on rev_info.reverse from Simon 'corecode' Schubert.]

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-20 23:46:53 -08:00
03840fc32d Allow in_merge_bases() to take more than one reference commits.
The internal function in_merge_bases(A, B) is used to make sure
that commit A is an ancestor of commit B.  This changes the
signature of it to take an array of B's and updates its current
callers.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-09 17:57:03 -08:00
71dfbf224f Make merge-base a built-in.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-09 17:57:03 -08:00
1a9eb3b9d5 git-diff/git-apply: make diff output a bit friendlier to GNU patch (part 2)
Somebody was wondering on #git channel why a git generated diff
does not apply with GNU patch when the filename contains a SP.
It is because GNU patch expects to find TAB (and trailing timestamp)
on ---/+++ (old_name and new_name) lines after the filenames.

The "diff --git" output format was carefully designed to be
compatible with GNU patch where it can, but whitespace
characters were always a pain.

This adds an extra TAB (but not trailing timestamp) to old_name
and new_name lines of git-diff output when the filename has a SP
in it.  An earlier patch updated git-apply to prepare for this.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-11-21 21:27:51 -08:00
348 changed files with 15698 additions and 6109 deletions

6
.gitignore vendored
View File

@ -13,6 +13,7 @@ git-archive
git-bisect
git-blame
git-branch
git-bundle
git-cat-file
git-check-ref-format
git-checkout
@ -33,11 +34,11 @@ git-daemon
git-diff
git-diff-files
git-diff-index
git-diff-stages
git-diff-tree
git-describe
git-fast-import
git-fetch
git-fetch--tool
git-fetch-pack
git-findtags
git-fmt-merge-msg
@ -75,6 +76,7 @@ git-merge-ours
git-merge-recursive
git-merge-resolve
git-merge-stupid
git-mergetool
git-mktag
git-mktree
git-name-rev
@ -101,7 +103,6 @@ git-repo-config
git-request-pull
git-rerere
git-reset
git-resolve
git-rev-list
git-rev-parse
git-revert
@ -141,6 +142,7 @@ git-whatchanged
git-write-tree
git-core-*/?*
gitweb/gitweb.cgi
test-chmtime
test-date
test-delta
test-dump-cache-tree

View File

@ -27,6 +27,7 @@ Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
René Scharfe <rene.scharfe@lsrfire.ath.cx>
Robert Fitzsimons <robfitz@273k.net>
Sam Vilain <sam@vilain.net>
Santi Béjar <sbejar@gmail.com>
Sean Estabrooks <seanlkml@sympatico.ca>
Shawn O. Pearce <spearce@spearce.org>

View File

@ -0,0 +1,192 @@
GIT v1.5.1 Release Notes
========================
Updates since v1.5.0
--------------------
* Deprecated commands and options.
- git-diff-stages and git-resolve have been removed.
* New commands and options.
- "git log" and friends take --reverse, which instructs them
to give their output in the order opposite from their usual.
They typically output from new to old, but with this option
their output would read from old to new. "git shortlog"
usually lists older commits first, but with this option,
they are shown from new to old.
- "git log --pretty=format:<string>" to allow more flexible
custom log output.
- "git diff" learned --ignore-space-at-eol. This is a weaker
form of --ignore-space-change.
- "git diff --no-index pathA pathB" can be used as diff
replacement with git specific enhancements.
- "git diff --no-index" can read from '-' (standard input).
- "git diff" also learned --exit-code to exit with non-zero
status when it found differences. In the future we might
want to make this the default but that would be a rather big
backward incompatible change; it will stay as an option for
now.
- "git diff --quiet" is --exit-code with output turned off,
meant for scripted use to quickly determine if there is any
tree-level difference.
- Textual patch generation with "git diff" without -w/-b
option has been significantly optimized. "git blame" got
faster because of the same change.
- "git log" and "git rev-list" has been optimized
significantly when they are used with pathspecs.
- "git branch --track" can be used to set up configuration
variables to help it easier to base your work on branches
you track from a remote site.
- "git format-patch --attach" now emits attachments. Use
--inline to get an inlined multipart/mixed.
- "git name-rev" learned --refs=<pattern>, to limit the tags
used for naming the given revisions only to the ones
matching the given pattern.
- "git remote update" is to run "git fetch" for defined remotes
to update tracking branches.
- "git cvsimport" can now take '-d' to talk with a CVS
repository different from what are recorded in CVS/Root
(overriding it with environment CVSROOT does not work).
- "git bundle" can help sneaker-netting your changes between
repositories.
- "git mergetool" can help 3-way file-level conflict
resolution with your favorite graphical merge tools.
- A new configuration "core.symlinks" can be used to disable
symlinks on filesystems that do not support them; they are
checked out as regular files instead.
- You can name a commit object with its first line of the
message. The syntax to use is ':/message text'. E.g.
$ git show ":/object name: introduce ':/<oneline prefix>' notation"
means the same thing as:
$ git show 28a4d940443806412effa246ecc7768a21553ec7
- "git bisect" learned a new command "run" that takes a script
to run after each revision is checked out to determine if it
is good or bad, to automate the bisection process.
* Updated behaviour of existing commands.
- "git fsck" does not barf on corrupt loose objects.
- "git archimport" allows remapping when coming up with git
branch names from arch names.
- git-svn got almost a rewrite.
- core.autocrlf configuration, when set to 'true', makes git
to convert CRLF at the end of lines in text files to LF when
reading from the filesystem, and convert in reverse when
writing to the filesystem. The variable can be set to
'input', in which case the conversion happens only while
reading from the filesystem but files are written out with
LF at the end of lines. Currently, which paths to consider
'text' (i.e. be subjected to the autocrlf mechanism) is
decided purely based on the contents, but the plan is to
allow users to explicitly override this heuristic based on
paths.
- The behaviour of 'git-apply', when run in a subdirectory,
without --index nor --cached were inconsistent with that of
the command with these options. This was fixed to match the
behaviour with --index. A patch that is meant to be applied
with -p1 from the toplevel of the project tree can be
applied with any custom -p<n> option. A patch that is not
relative to the toplevel needs to be applied with -p<n>
option with or without --index (or --cached).
- "git diff" outputs a trailing HT when pathnames have embedded
SP on +++/--- header lines, in order to help "GNU patch" to
parse its output. "git apply" was already updated to accept
this modified output format since ce74618d (Sep 22, 2006).
- "git cvsserver" runs hooks/update and honors its exit status.
- "git cvsserver" can be told to send everything with -kb.
- "git diff --check" also honors the --color output option.
- "git name-rev" used to stress the fact that a ref is a tag too
much, by saying something like "v1.2.3^0~22". It now says
"v1.2.3~22" in such a case (it still says "v1.2.3^0" if it does
not talk about an ancestor of the commit that is tagged, which
makes sense).
- "git rev-list --boundary" now shows boundary markers for the
commits omitted by --max-age and --max-count condition.
- The configuration mechanism now reads $(prefix)/etc/gitconfig.
- "git apply --verbose" shows what preimage lines were wanted
when it couldn't find them.
- "git status" in a read-only repository got a bit saner.
- "git fetch" (hence "git clone" and "git pull") are less
noisy when the output does not go to tty.
- "git fetch" between repositories with many refs were slow
even when there are not many changes that needed
transferring. This has been sped up by partially rewriting
the heaviest parts in C.
- "git mailinfo" which splits an e-mail into a patch and the
metainformation was rewritten, thanks to Don Zickus. It
handles nested multipart better.
- send-email learned configurable bcc and chain-reply-to.
- "git remote show $remote" also talks about branches that
would be pushed if you run "git push remote".
- Using objects from packs is now seriouly optimized by clever
use of a cache. This should be most noticeable in git-log
family of commands that involve reading many tree objects.
In addition, traversing revisions while filtering changes
with pathspecs is made faster by terminating the comparison
between the trees as early as possible.
* Hooks
- The part to send out notification e-mails was removed from
the sample update hook, as it was not an appropriate place
to do so.
* Others
- git-revert, git-gc and git-cherry-pick are now built-ins.
--
exec >/var/tmp/1
O=v1.5.1-rc1-63-g12d6697
echo O=`git describe master`
git shortlog --no-merges $O..master ^maint
# Local Variables:
# mode: text
# End:

View File

@ -70,6 +70,7 @@ git-archive mainporcelain
git-bisect mainporcelain
git-blame ancillaryinterrogators
git-branch mainporcelain
git-bundle mainporcelain
git-cat-file plumbinginterrogators
git-checkout-index plumbingmanipulators
git-checkout mainporcelain
@ -90,7 +91,6 @@ git-describe mainporcelain
git-diff-files plumbinginterrogators
git-diff-index plumbinginterrogators
git-diff mainporcelain
git-diff-stages plumbinginterrogators
git-diff-tree plumbinginterrogators
git-fast-import ancillarymanipulators
git-fetch mainporcelain
@ -124,6 +124,7 @@ git-merge-index plumbingmanipulators
git-merge mainporcelain
git-merge-one-file purehelpers
git-merge-tree ancillaryinterrogators
git-mergetool ancillarymanipulators
git-mktag plumbingmanipulators
git-mktree plumbingmanipulators
git-mv mainporcelain
@ -150,7 +151,6 @@ git-remote ancillarymanipulators
git-request-pull foreignscminterface
git-rerere ancillaryinterrogators
git-reset mainporcelain
git-resolve mainporcelain
git-revert mainporcelain
git-rev-list plumbinginterrogators
git-rev-parse ancillaryinterrogators

View File

@ -5,7 +5,8 @@ The git configuration file contains a number of variables that affect
the git command's behavior. `.git/config` file for each repository
is used to store the information for that repository, and
`$HOME/.gitconfig` is used to store per user information to give
fallback values for `.git/config` file.
fallback values for `.git/config` file. The file `/etc/gitconfig`
can be used to store system-wide defaults.
They can be used by both the git plumbing
and the porcelains. The variables are divided into sections, where
@ -116,6 +117,13 @@ core.fileMode::
the working copy are ignored; useful on broken filesystems like FAT.
See gitlink:git-update-index[1]. True by default.
core.symlinks::
If false, symbolic links are checked out as small plain files that
contain the link text. gitlink:git-update-index[1] and
gitlink:git-add[1] will not change the recorded type to regular
file. Useful on filesystems like FAT that do not support
symbolic links. True by default.
core.gitProxy::
A "proxy command" to execute (as 'command host port') instead
of establishing direct connection to the remote server when
@ -232,6 +240,19 @@ the largest projects. You probably do not need to adjust this value.
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
core.deltaBaseCacheLimit::
Maximum number of bytes to reserve for caching base objects
that multiple deltafied objects reference. By storing the
entire decompressed base objects in a cache Git is able
to avoid unpacking and decompressing frequently used base
objects multiple times.
+
Default is 16 MiB on all platforms. This should be reasonable
for all users/operating systems, except on the largest projects.
You probably do not need to adjust this value.
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
alias.*::
Command aliases for the gitlink:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation
@ -264,6 +285,10 @@ branch.<name>.merge::
`git fetch`) to lookup the default branch for merging. Without
this option, `git pull` defaults to merge the first refspec fetched.
Specify multiple values to get an octopus merge.
If you wish to setup `git pull` so that it merges into <name> from
another branch in the local repository, you can point
branch.<name>.merge to the desired branch, and use the special setting
`.` (a period) for branch.<name>.remote.
color.branch::
A boolean to enable/disable color in the output of
@ -445,6 +470,11 @@ merge.summary::
Whether to include summaries of merged commits in newly created
merge commit messages. False by default.
merge.tool::
Controls which merge resolution program is used by
gitlink:git-mergetool[l]. Valid values are: "kdiff3", "tkdiff",
"meld", "xxdiff", "emerge", "vimdiff"
merge.verbosity::
Controls the amount of output shown by the recursive merge
strategy. Level 0 outputs nothing except a final error
@ -475,6 +505,10 @@ remote.<name>.push::
The default set of "refspec" for gitlink:git-push[1]. See
gitlink:git-push[1].
remote.<name>.skipDefaultUpdate::
If true, this remote will be skipped by default when updating
using the remote subcommand of gitlink:git-remote[1].
remote.<name>.receivepack::
The default program to execute on the remote side when pushing. See
option \--exec of gitlink:git-push[1].
@ -483,6 +517,14 @@ remote.<name>.uploadpack::
The default program to execute on the remote side when fetching. See
option \--exec of gitlink:git-fetch-pack[1].
remote.<name>.tagopt::
Setting this value to --no-tags disables automatic tag following when fetching
from remote <name>
remotes.<group>::
The list of remotes which are fetched by "git remote update
<group>". See gitlink:git-remote[1].
repack.usedeltabaseoffset::
Allow gitlink:git-repack[1] to create packs that uses
delta-base offset. Defaults to false.

View File

@ -588,4 +588,5 @@ stages to temporary files and calls a "merge" script on it:
git-merge-index git-merge-one-file hello.c
and that is what higher level `git resolve` is implemented with.
and that is what higher level `git merge -s resolve` is implemented
with.

View File

@ -977,7 +977,7 @@ see more complex cases.
Now, let's pretend you are the one who did all the work in
`mybranch`, and the fruit of your hard work has finally been merged
to the `master` branch. Let's go back to `mybranch`, and run
resolve to get the "upstream changes" back to your branch.
`git merge` to get the "upstream changes" back to your branch.
------------
$ git checkout mybranch
@ -996,7 +996,7 @@ Fast forward
----------------
Because your branch did not contain anything more than what are
already merged into the `master` branch, the resolve operation did
already merged into the `master` branch, the merge operation did
not actually do a merge. Instead, it just updated the top of
the tree of your branch to that of the `master` branch. This is
often called 'fast forward' merge.
@ -1099,11 +1099,11 @@ programs, which are 'commit walkers'; they outlived their
usefulness when git Native and SSH transports were introduced,
and not used by `git pull` or `git push` scripts.
Once you fetch from the remote repository, you `resolve` that
Once you fetch from the remote repository, you `merge` that
with your current branch.
However -- it's such a common thing to `fetch` and then
immediately `resolve`, that it's called `git pull`, and you can
immediately `merge`, that it's called `git pull`, and you can
simply do
----------------

View File

@ -140,6 +140,9 @@
-a::
Shorthand for "--text".
--ignore-space-at-eol::
Ignore changes in white spaces at EOL.
--ignore-space-change::
Ignore changes in amount of white space. This ignores white
space at line end, and consider all other sequences of one or
@ -156,5 +159,13 @@
-w::
Shorthand for "--ignore-all-space".
--exit-code::
Make the program exit with codes similar to diff(1).
That is, it exits with 1 if there were differences and
0 means no differences.
--quiet::
Disable all output of the program. Implies --exit-code.
For more detailed explanation on these common options, see also
link:diffcore.html[diffcore documentation].

View File

@ -6,8 +6,8 @@ June 2005
Introduction
------------
The diff commands git-diff-index, git-diff-files, git-diff-tree, and
git-diff-stages can be told to manipulate differences they find in
The diff commands git-diff-index, git-diff-files, and git-diff-tree
can be told to manipulate differences they find in
unconventional ways before showing diff(1) output. The manipulation
is collectively called "diffcore transformation". This short note
describes what they are and how to use them to produce diff outputs
@ -30,9 +30,6 @@ files:
- git-diff-tree compares contents of two "tree" objects;
- git-diff-stages compares contents of blobs at two stages in an
unmerged index file.
In all of these cases, the commands themselves compare
corresponding paths in the two sets of files. The result of
comparison is passed from these commands to what is internally

View File

@ -87,6 +87,33 @@ default. You could use `--no-utf8` to override this.
DISCUSSION
----------
The commit author name is taken from the "From: " line of the
message, and commit author time is taken from the "Date: " line
of the message. The "Subject: " line is used as the title of
the commit, after stripping common prefix "[PATCH <anything>]".
It is supposed to describe what the commit is about concisely as
a one line text.
The body of the message (iow, after a blank line that terminates
RFC2822 headers) can begin with "Subject: " and "From: " lines
that are different from those of the mail header, to override
the values of these fields.
The commit message is formed by the title taken from the
"Subject: ", a blank line and the body of the message up to
where the patch begins. Excess whitespaces at the end of the
lines are automatically stripped.
The patch is expected to be inline, directly following the
message. Any line that is of form:
* three-dashes and end-of-line, or
* a line that begins with "diff -", or
* a line that begins with "Index: "
is taken as the beginning of a patch, and the commit log message
is terminated before the first occurrence of such a line.
When initially invoking it, you give it names of the mailboxes
to crunch. Upon seeing the first patch that does not apply, it
aborts in the middle, just like 'git-applymbox' does. You can

View File

@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git-archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
<archive/branch> [ <archive/branch> ]
<archive/branch>[:<git-branch>] ...
DESCRIPTION
-----------
@ -39,6 +39,19 @@ directory. To follow the development of a project that uses Arch, rerun
`git-archimport` with the same parameters as the initial import to perform
incremental imports.
While git-archimport will try to create sensible branch names for the
archives that it imports, it is also possible to specify git branch names
manually. To do so, write a git branch name after each <archive/branch>
parameter, separated by a colon. This way, you can shorten the Arch
branch names and convert Arch jargon to git jargon, for example mapping a
"PROJECT--devo--VERSION" branch to "master".
Associating multiple Arch branches to one git branch is possible; the
result will make the most sense only if no commits are made to the first
branch, after the second branch is created. Still, this is useful to
convert Arch repositories that had been rotated periodically.
MERGES
------
Patch merge data from Arch is used to mark merges in git as well. git
@ -73,7 +86,9 @@ OPTIONS
Use this for compatibility with old-style branch names used by
earlier versions of git-archimport. Old-style branch names
were category--branch, whereas new-style branch names are
archive,category--branch--version.
archive,category--branch--version. In both cases, names given
on the command-line will override the automatically-generated
ones.
-D <depth>::
Follow merge ancestry and attempt to import trees that have been

View File

@ -12,8 +12,8 @@ SYNOPSIS
DESCRIPTION
-----------
The command takes various subcommands, and different options
depending on the subcommand:
The command takes various subcommands, and different options depending
on the subcommand:
git bisect start [<paths>...]
git bisect bad <rev>
@ -22,30 +22,34 @@ depending on the subcommand:
git bisect visualize
git bisect replay <logfile>
git bisect log
git bisect run <cmd>...
This command uses 'git-rev-list --bisect' option to help drive
the binary search process to find which change introduced a bug,
given an old "good" commit object name and a later "bad" commit
object name.
This command uses 'git-rev-list --bisect' option to help drive the
binary search process to find which change introduced a bug, given an
old "good" commit object name and a later "bad" commit object name.
Basic bisect commands: start, bad, good
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The way you use it is:
------------------------------------------------
$ git bisect start
$ git bisect bad # Current version is bad
$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version
# tested that was good
$ git bisect bad # Current version is bad
$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version
# tested that was good
------------------------------------------------
When you give at least one bad and one good versions, it will
bisect the revision tree and say something like:
When you give at least one bad and one good versions, it will bisect
the revision tree and say something like:
------------------------------------------------
Bisecting: 675 revisions left to test after this
------------------------------------------------
and check out the state in the middle. Now, compile that kernel, and boot
it. Now, let's say that this booted kernel works fine, then just do
and check out the state in the middle. Now, compile that kernel, and
boot it. Now, let's say that this booted kernel works fine, then just
do
------------------------------------------------
$ git bisect good # this one is good
@ -57,12 +61,15 @@ which will now say
Bisecting: 337 revisions left to test after this
------------------------------------------------
and you continue along, compiling that one, testing it, and depending on
whether it is good or bad, you say "git bisect good" or "git bisect bad",
and ask for the next bisection.
and you continue along, compiling that one, testing it, and depending
on whether it is good or bad, you say "git bisect good" or "git bisect
bad", and ask for the next bisection.
Until you have no more left, and you'll have been left with the first bad
kernel rev in "refs/bisect/bad".
Until you have no more left, and you'll have been left with the first
bad kernel rev in "refs/bisect/bad".
Bisect reset
~~~~~~~~~~~~
Oh, and then after you want to reset to the original head, do a
@ -70,10 +77,13 @@ Oh, and then after you want to reset to the original head, do a
$ git bisect reset
------------------------------------------------
to get back to the master branch, instead of being in one of the bisection
branches ("git bisect start" will do that for you too, actually: it will
reset the bisection state, and before it does that it checks that you're
not using some old bisection branch).
to get back to the master branch, instead of being in one of the
bisection branches ("git bisect start" will do that for you too,
actually: it will reset the bisection state, and before it does that
it checks that you're not using some old bisection branch).
Bisect visualize
~~~~~~~~~~~~~~~~
During the bisection process, you can say
@ -83,9 +93,17 @@ $ git bisect visualize
to see the currently remaining suspects in `gitk`.
The good/bad input is logged, and `git bisect
log` shows what you have done so far. You can truncate its
output somewhere and save it in a file, and run
Bisect log and bisect replay
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The good/bad input is logged, and
------------
$ git bisect log
------------
shows what you have done so far. You can truncate its output somewhere
and save it in a file, and run
------------
$ git bisect replay that-file
@ -94,12 +112,16 @@ $ git bisect replay that-file
if you find later you made a mistake telling good/bad about a
revision.
If in a middle of bisect session, you know what the bisect
suggested to try next is not a good one to test (e.g. the change
the commit introduces is known not to work in your environment
and you know it does not have anything to do with the bug you
are chasing), you may want to find a near-by commit and try that
instead. It goes something like this:
Avoiding to test a commit
~~~~~~~~~~~~~~~~~~~~~~~~~
If in a middle of bisect session, you know what the bisect suggested
to try next is not a good one to test (e.g. the change the commit
introduces is known not to work in your environment and you know it
does not have anything to do with the bug you are chasing), you may
want to find a near-by commit and try that instead.
It goes something like this:
------------
$ git bisect good/bad # previous round was good/bad.
@ -109,18 +131,52 @@ $ git reset --hard HEAD~3 # try 3 revs before what
# was suggested
------------
Then compile and test the one you chose to try. After that,
tell bisect what the result was as usual.
Then compile and test the one you chose to try. After that, tell
bisect what the result was as usual.
You can further cut down the number of trials if you know what
part of the tree is involved in the problem you are tracking
down, by giving paths parameters when you say `bisect start`,
like this:
Cutting down bisection by giving path parameter to bisect start
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can further cut down the number of trials if you know what part of
the tree is involved in the problem you are tracking down, by giving
paths parameters when you say `bisect start`, like this:
------------
$ git bisect start arch/i386 include/asm-i386
------------
Bisect run
~~~~~~~~~~
If you have a script that can tell if the current source code is good
or bad, you can automatically bisect using:
------------
$ git bisect run my_script
------------
Note that the "run" script (`my_script` in the above example) should
exit with code 0 in case the current source code is good and with a
code between 1 and 127 (included) in case the current source code is
bad.
Any other exit code will abort the automatic bisect process. (A
program that does "exit(-1)" leaves $? = 255, see exit(3) manual page,
the value is chopped with "& 0377".)
You may often find that during bisect you want to have near-constant
tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
"revision that does not have this commit needs this patch applied to
work around other problem this bisection is not interested in")
applied to the revision being tested.
To cope with such a situation, after the inner git-bisect finds the
next revision to test, with the "run" script, you can apply that tweak
before compiling, run the real test, and after the test decides if the
revision (possibly with the needed tweaks) passed the test, rewind the
tree to the pristine state. Finally the "run" script can exit with
the status of the real test to let "git bisect run" command loop to
know the outcome.
Author
------

View File

@ -8,8 +8,9 @@ git-branch - List, create, or delete branches
SYNOPSIS
--------
[verse]
'git-branch' [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]
'git-branch' [-l] [-f] <branchname> [<start-point>]
'git-branch' [--color | --no-color] [-r | -a]
[-v [--abbrev=<length> | --no-abbrev]]
'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
'git-branch' (-m | -M) [<oldbranch>] <newbranch>
'git-branch' (-d | -D) [-r] <branchname>...
@ -25,6 +26,13 @@ It will start out with a head equal to the one given as <start-point>.
If no <start-point> is given, the branch will be created with a head
equal to that of the currently checked out branch.
When a local branch is started off a remote branch, git can setup the
branch so that gitlink:git-pull[1] will appropriately merge from that
remote branch. If this behavior is desired, it is possible to make it
the default using the global `branch.autosetupmerge` configuration
flag. Otherwise, it can be chosen per-branch using the `--track`
and `--no-track` options.
With a '-m' or '-M' option, <oldbranch> will be renamed to <newbranch>.
If <oldbranch> had a corresponding reflog, it is renamed to match
<newbranch>, and a reflog entry is created to remember the branch
@ -80,6 +88,9 @@ OPTIONS
Alter minimum display length for sha1 in output listing,
default value is 7.
--no-abbrev::
Display the full sha1s in output listing rather than abbreviating them.
<branchname>::
The name of the branch to create or delete.
The new branch name must pass all checks defined by

View File

@ -0,0 +1,139 @@
git-bundle(1)
=============
NAME
----
git-bundle - Move objects and refs by archive
SYNOPSIS
--------
'git-bundle' create <file> [git-rev-list args]
'git-bundle' verify <file>
'git-bundle' list-heads <file> [refname...]
'git-bundle' unbundle <file> [refname...]
DESCRIPTION
-----------
Some workflows require that one or more branches of development on one
machine be replicated on another machine, but the two machines cannot
be directly connected so the interactive git protocols (git, ssh,
rsync, http) cannot be used. This command provides support for
git-fetch and git-pull to operate by packaging objects and references
in an archive at the originating machine, then importing those into
another repository using gitlink:git-fetch[1] and gitlink:git-pull[1]
after moving the archive by some means (i.e., by sneakernet). As no
direct connection between repositories exists, the user must specify a
basis for the bundle that is held by the destination repository: the
bundle assumes that all objects in the basis are already in the
destination repository.
OPTIONS
-------
create <file>::
Used to create a bundle named 'file'. This requires the
git-rev-list arguments to define the bundle contents.
verify <file>::
Used to check that a bundle file is valid and will apply
cleanly to the current repository. This includes checks on the
bundle format itself as well as checking that the prerequisite
commits exist and are fully linked in the current repository.
git-bundle prints a list of missing commits, if any, and exits
with non-zero status.
list-heads <file>::
Lists the references defined in the bundle. If followed by a
list of references, only references matching those given are
printed out.
unbundle <file>::
Passes the objects in the bundle to gitlink:git-index-pack[1]
for storage in the repository, then prints the names of all
defined references. If a reflist is given, only references
matching those in the given list are printed. This command is
really plumbing, intended to be called only by
gitlink:git-fetch[1].
[git-rev-list-args...]::
A list of arguments, acceptable to git-rev-parse and
git-rev-list, that specify the specific objects and references
to transport. For example, "master~10..master" causes the
current master reference to be packaged along with all objects
added since its 10th ancestor commit. There is no explicit
limit to the number of references and objects that may be
packaged.
[refname...]::
A list of references used to limit the references reported as
available. This is principally of use to git-fetch, which
expects to receive only those references asked for and not
necessarily everything in the pack (in this case, git-bundle is
acting like gitlink:git-fetch-pack[1]).
SPECIFYING REFERENCES
---------------------
git-bundle will only package references that are shown by
git-show-ref: this includes heads, tags, and remote heads. References
such as master~1 cannot be packaged, but are perfectly suitable for
defining the basis. More than one reference may be packaged, and more
than one basis can be specified. The objects packaged are those not
contained in the union of the given bases. Each basis can be
specified explicitly (e.g., ^master~10), or implicitly (e.g.,
master~10..master, master --since=10.days.ago).
It is very important that the basis used be held by the destination.
It is okay to err on the side of conservatism, causing the bundle file
to contain objects already in the destination as these are ignored
when unpacking at the destination.
EXAMPLE
-------
Assume two repositories exist as R1 on machine A, and R2 on machine B.
For whatever reason, direct connection between A and B is not allowed,
but we can move data from A to B via some mechanism (CD, email, etc).
We want to update R2 with developments made on branch master in R1.
We set a tag in R1 (lastR2bundle) after the previous such transport,
and move it afterwards to help build the bundle.
in R1 on A:
$ git-bundle create mybundle master ^lastR2bundle
$ git tag -f lastR2bundle master
(move mybundle from A to B by some mechanism)
in R2 on B:
$ git-bundle verify mybundle
$ git-fetch mybundle refspec
where refspec is refInBundle:localRef
Also, with something like this in your config:
[remote "bundle"]
url = /home/me/tmp/file.bdl
fetch = refs/heads/*:refs/remotes/origin/*
You can first sneakernet the bundle file to ~/tmp/file.bdl and
then these commands:
$ git ls-remote bundle
$ git fetch bundle
$ git pull bundle
would treat it as if it is talking with a remote side over the
network.
Author
------
Written by Mark Levedahl <mdl123@verizon.net>
GIT
---
Part of the gitlink:git[7] suite

View File

@ -8,7 +8,7 @@ git-checkout - Checkout and switch to a branch
SYNOPSIS
--------
[verse]
'git-checkout' [-q] [-f] [-b <new_branch> [-l]] [-m] [<branch>]
'git-checkout' [-q] [-f] [-b [--track | --no-track] <new_branch> [-l]] [-m] [<branch>]
'git-checkout' [<tree-ish>] <paths>...
DESCRIPTION
@ -18,7 +18,8 @@ When <paths> are not given, this command switches branches by
updating the index and working tree to reflect the specified
branch, <branch>, and updating HEAD to be <branch> or, if
specified, <new_branch>. Using -b will cause <new_branch> to
be created.
be created; in this case you can use the --track or --no-track
options, which will be passed to `git branch`.
When <paths> are given, this command does *not* switch
branches. It updates the named paths in the working tree from
@ -45,6 +46,16 @@ OPTIONS
by gitlink:git-check-ref-format[1]. Some of these checks
may restrict the characters allowed in a branch name.
--track::
When -b is given and a branch is created off a remote branch,
setup so that git-pull will automatically retrieve data from
the remote branch.
--no-track::
When -b is given and a branch is created off a remote branch,
force that git-pull will automatically retrieve data from
the remote branch independent of the configuration settings.
-l::
Create the new branch's ref log. This activates recording of
all changes to made the branch ref, enabling use of date

View File

@ -8,8 +8,9 @@ git-commit - Record changes to the repository
SYNOPSIS
--------
[verse]
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg> |
--amend] [--no-verify] [-e] [--author <author>]
'git-commit' [-a | --interactive] [-s] [-v]
[(-c | -C) <commit> | -F <file> | -m <msg> | --amend]
[--no-verify] [-e] [--author <author>]
[--] [[-i | -o ]<file>...]
DESCRIPTION
@ -35,6 +36,10 @@ methods:
before, and to automatically "rm" files that have been
removed from the working tree, and perform the actual commit.
5. by using the --interactive switch with the 'commit' command to decide one
by one which files should be part of the commit, before finalizing the
operation. Currently, this is done by invoking `git-add --interactive`.
The gitlink:git-status[1] command can be used to obtain a
summary of what is included by any of the above for the next
commit by giving the same set of parameters you would give to

View File

@ -16,6 +16,8 @@ SYNOPSIS
'git-config' [--global] [type] --get-all name [value_regex]
'git-config' [--global] [type] --unset name [value_regex]
'git-config' [--global] [type] --unset-all name [value_regex]
'git-config' [--global] [type] --rename-section old_name new_name
'git-config' [--global] [type] --remove-section name
'git-config' [--global] -l | --list
DESCRIPTION
@ -74,6 +76,12 @@ OPTIONS
--global::
Use global ~/.gitconfig file rather than the repository .git/config.
--remove-section::
Remove the given section from the configuration file.
--rename-section::
Rename the given section to a new name.
--unset::
Remove the line matching the key from config file.

View File

@ -8,7 +8,7 @@ git-cvsexportcommit - Export a single commit to a CVS checkout
SYNOPSIS
--------
'git-cvsexportcommit' [-h] [-v] [-c] [-P] [-p] [-a] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
'git-cvsexportcommit' [-h] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
DESCRIPTION
@ -43,6 +43,11 @@ OPTIONS
Add authorship information. Adds Author line, and Committer (if
different from Author) to the message.
-d::
Set an alternative CVSROOT to use. This corresponds to the CVS
-d parameter. Usually users will not want to set this, except
if using CVS in an asymmetric fashion.
-f::
Force the merge even if the files are not up to date.

View File

@ -8,7 +8,7 @@ git-diff-files - Compares files in the working tree and the index
SYNOPSIS
--------
'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc|-n|--no-index] [<common diff options>] [<path>...]
DESCRIPTION
-----------
@ -36,6 +36,9 @@ omit diff output for unmerged entries and just show "Unmerged".
diff, similar to the way 'diff-tree' shows a merge
commit with these flags.
\-n,\--no-index::
Compare the two given files / directories.
-q::
Remain silent even on nonexistent files

View File

@ -1,42 +0,0 @@
git-diff-stages(1)
==================
NAME
----
git-diff-stages - Compares two merge stages in the index
SYNOPSIS
--------
'git-diff-stages' [<common diff options>] <stage1> <stage2> [<path>...]
DESCRIPTION
-----------
DEPRECATED and will be removed in 1.5.1.
Compares the content and mode of the blobs in two stages in an
unmerged index file.
OPTIONS
-------
include::diff-options.txt[]
<stage1>,<stage2>::
The stage number to be compared.
Output format
-------------
include::diff-format.txt[]
Author
------
Written by Junio C Hamano <junkio@cox.net>
Documentation
--------------
Documentation by Junio C Hamano.
GIT
---
Part of the gitlink:git[7] suite

View File

@ -23,6 +23,10 @@ tree and the index file, or the index file and the working tree.
further add to the index but you still haven't. You can
stage these changes by using gitlink:git-add[1].
If exactly two paths are given, and at least one is untracked,
compare the two files / directories. This behavior can be
forced by --no-index.
'git-diff' [--options] --cached [<commit>] [--] [<path>...]::
This form is to view the changes you staged for the next

View File

@ -62,7 +62,18 @@ OPTIONS
Dumps the internal marks table to <file> when complete.
Marks are written one per line as `:markid SHA-1`.
Frontends can use this file to validate imports after they
have been completed.
have been completed, or to save the marks table across
incremental runs. As <file> is only opened and truncated
at checkpoint (or completion) the same path can also be
safely given to \--import-marks.
--import-marks=<file>::
Before processing any input, load the marks specified in
<file>. The input file must exist, must be readable, and
must use the same format as produced by \--export-marks.
Multiple options may be supplied to import more than one
set of marks. If a mark is defined to different values,
the last file wins.
--export-pack-edges=<file>::
After creating a packfile, print a line of data to

View File

@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository
SYNOPSIS
--------
'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [-v] [<host>:]<directory> [<refs>...]
'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]
DESCRIPTION
-----------
@ -63,6 +63,9 @@ OPTIONS
\--depth=<n>::
Limit fetching to ancestor-chains not longer than n.
\--no-progress::
Do not show the progress.
\-v::
Run verbosely.

View File

@ -9,8 +9,9 @@ git-format-patch - Prepare patches for e-mail submission
SYNOPSIS
--------
[verse]
'git-format-patch' [<common diff options>] [-n | -k] [-o <dir> | --stdout]
[--attach] [--thread] [-s | --signoff] [--start-number <n>]
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--thread]
[--attach[=<boundary>] | --inline[=<boundary>]]
[-s | --signoff] [<common diff options>] [--start-number <n>]
[--in-reply-to=Message-Id] [--suffix=.<sfx>]
[--ignore-if-in-upstream]
<since>[..<until>]
@ -70,8 +71,15 @@ include::diff-options.txt[]
Print all commits to the standard output in mbox format,
instead of creating a file for each one.
--attach::
Create attachments instead of inlining patches.
--attach[=<boundary>]::
Create multipart/mixed attachment, the first part of
which is the commit message and the patch itself in the
second part, with "Content-Disposition: attachment".
--inline[=<boundary>]::
Create multipart/mixed attachment, the first part of
which is the commit message and the patch itself in the
second part, with "Content-Disposition: inline".
--thread::
Add In-Reply-To and References headers to make the second and

View File

@ -38,6 +38,11 @@ include::pretty-formats.txt[]
and <until>, see "SPECIFYING REVISIONS" section in
gitlink:git-rev-parse[1].
--first-parent::
Follow only the first parent commit upon seeing a merge
commit. This option gives a better overview of the
evolution of a particular branch.
-p::
Show the change the commit introduces in a patch form.

View File

@ -0,0 +1,46 @@
git-mergetool(1)
================
NAME
----
git-mergetool - Run merge conflict resolution tools to resolve merge conflicts
SYNOPSIS
--------
'git-mergetool' [--tool=<tool>] [<file>]...
DESCRIPTION
-----------
Use 'git mergetool' to run one of several merge utilities to resolve
merge conflicts. It is typically run after gitlink:git-merge[1].
If one or more <file> parameters are given, the merge tool program will
be run to resolve differences on each file. If no <file> names are
specified, 'git mergetool' will run the merge tool program on every file
with merge conflicts.
OPTIONS
-------
-t or --tool=<tool>::
Use the merge resolution program specified by <tool>.
Valid merge tools are:
kdiff3, tkdiff, meld, xxdiff, emerge, and vimdiff.
If a merge resolution program is not specified, 'git mergetool'
will use the configuration variable merge.tool. If the
configuration variable merge.tool is not set, 'git mergetool'
will pick a suitable default.
Author
------
Written by Theodore Y Ts'o <tytso@mit.edu>
Documentation
--------------
Documentation by Theodore Y Ts'o.
GIT
---
Part of the gitlink:git[7] suite

View File

@ -8,7 +8,8 @@ git-name-rev - Find symbolic names for given revs
SYNOPSIS
--------
'git-name-rev' [--tags] ( --all | --stdin | <committish>... )
'git-name-rev' [--tags] [--refs=<pattern>]
( --all | --stdin | <committish>... )
DESCRIPTION
-----------
@ -22,6 +23,9 @@ OPTIONS
--tags::
Do not use branch names, but only tags to name the commits
--refs=<pattern>::
Only use refs whose names match a given shell pattern.
--all::
List all commits reachable from all refs

View File

@ -25,62 +25,127 @@ The command allows for creation and fast forwarding of sha1 refs
local end receive-pack runs, but to the user who is sitting at
the send-pack end, it is updating the remote. Confused?)
Before each ref is updated, if $GIT_DIR/hooks/update file exists
and executable, it is called with three parameters:
$GIT_DIR/hooks/update refname sha1-old sha1-new
The refname parameter is relative to $GIT_DIR; e.g. for the
master head this is "refs/heads/master". Two sha1 are the
object names for the refname before and after the update. Note
that the hook is called before the refname is updated, so either
sha1-old is 0{40} (meaning there is no such ref yet), or it
should match what is recorded in refname.
The hook should exit with non-zero status if it wants to
disallow updating the named ref. Otherwise it should exit with
zero.
Using this hook, it is easy to generate mails on updates to
the local repository. This example script sends a mail with
the commits pushed to the repository:
#!/bin/sh
# mail out commit update information.
if expr "$2" : '0*$' >/dev/null
then
echo "Created a new ref, with the following commits:"
git-rev-list --pretty "$2"
else
echo "New commits:"
git-rev-list --pretty "$3" "^$2"
fi |
mail -s "Changes to ref $1" commit-list@mydomain
exit 0
Another hook $GIT_DIR/hooks/post-update, if exists and
executable, is called with the list of refs that have been
updated. This can be used to implement repository wide cleanup
task if needed. The exit code from this hook invocation is
ignored; the only thing left for git-receive-pack to do at that
point is to exit itself anyway. This hook can be used, for
example, to run "git-update-server-info" if the repository is
packed and is served via a dumb transport.
#!/bin/sh
exec git-update-server-info
There are other real-world examples of using update and
post-update hooks found in the Documentation/howto directory.
git-receive-pack honours the receive.denyNonFastforwards flag, which
tells it if updates to a ref should be denied if they are not fast-forwards.
git-receive-pack honours the receive.denyNonFastForwards config
option, which tells it if updates to a ref should be denied if they
are not fast-forwards.
OPTIONS
-------
<directory>::
The repository to sync into.
pre-receive Hook
----------------
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists
and is executable, it will be invoked once with no parameters. The
standard input of the hook will be one line per ref to be updated:
sha1-old SP sha1-new SP refname LF
The refname value is relative to $GIT_DIR; e.g. for the master
head this is "refs/heads/master". The two sha1 values before
each refname are the object names for the refname before and after
the update. Refs to be created will have sha1-old equal to 0{40},
while refs to be deleted will have sha1-new equal to 0{40}, otherwise
sha1-old and sha1-new should be valid objects in the repository.
This hook is called before any refname is updated and before any
fast-forward checks are performed.
If the pre-receive hook exits with a non-zero exit status no updates
will be performed, and the update, post-receive and post-update
hooks will not be invoked either. This can be useful to quickly
bail out if the update is not to be supported.
update Hook
-----------
Before each ref is updated, if $GIT_DIR/hooks/update file exists
and is executable, it is invoked once per ref, with three parameters:
$GIT_DIR/hooks/update refname sha1-old sha1-new
The refname parameter is relative to $GIT_DIR; e.g. for the master
head this is "refs/heads/master". The two sha1 arguments are
the object names for the refname before and after the update.
Note that the hook is called before the refname is updated,
so either sha1-old is 0{40} (meaning there is no such ref yet),
or it should match what is recorded in refname.
The hook should exit with non-zero status if it wants to disallow
updating the named ref. Otherwise it should exit with zero.
Successful execution (a zero exit status) of this hook does not
ensure the ref will actully be updated, it is only a prerequisite.
As such it is not a good idea to send notices (e.g. email) from
this hook. Consider using the post-receive hook instead.
post-receive Hook
-----------------
After all refs were updated (or attempted to be updated), if any
ref update was successful, and if $GIT_DIR/hooks/post-receive
file exists and is executable, it will be invoke once with no
parameters. The standard input of the hook will be one line
for each successfully updated ref:
sha1-old SP sha1-new SP refname LF
The refname value is relative to $GIT_DIR; e.g. for the master
head this is "refs/heads/master". The two sha1 values before
each refname are the object names for the refname before and after
the update. Refs that were created will have sha1-old equal to
0{40}, while refs that were deleted will have sha1-new equal to
0{40}, otherwise sha1-old and sha1-new should be valid objects in
the repository.
Using this hook, it is easy to generate mails describing the updates
to the repository. This example script sends one mail message per
ref listing the commits pushed to the repository:
#!/bin/sh
# mail out commit update information.
while read oval nval ref
do
if expr "$oval" : '0*$' >/dev/null
then
echo "Created a new ref, with the following commits:"
git-rev-list --pretty "$nval"
else
echo "New commits:"
git-rev-list --pretty "$nval" "^$oval"
fi |
mail -s "Changes to ref $ref" commit-list@mydomain
done
exit 0
The exit code from this hook invocation is ignored, however a
non-zero exit code will generate an error message.
Note that it is possible for refname to not have sha1-new when this
hook runs. This can easily occur if another user modifies the ref
after it was updated by receive-pack, but before the hook was able
to evaluate it. It is recommended that hooks rely on sha1-new
rather than the current value of refname.
post-update Hook
----------------
After all other processing, if at least one ref was updated, and
if $GIT_DIR/hooks/post-update file exists and is executable, then
post-update will called with the list of refs that have been updated.
This can be used to implement any repository wide cleanup tasks.
The exit code from this hook invocation is ignored; the only thing
left for git-receive-pack to do at that point is to exit itself
anyway.
This hook can be used, for example, to run "git-update-server-info"
if the repository is packed and is served via a dumb transport.
#!/bin/sh
exec git-update-server-info
SEE ALSO
--------

View File

@ -13,6 +13,7 @@ SYNOPSIS
'git-remote' add [-t <branch>] [-m <branch>] [-f] <name> <url>
'git-remote' show <name>
'git-remote' prune <name>
'git-remote' update [group]
DESCRIPTION
-----------
@ -53,7 +54,17 @@ Gives some information about the remote <name>.
Deletes all stale tracking branches under <name>.
These stale branches have already been removed from the remote repository
referenced by <name>, but are still locally available in "remotes/<name>".
referenced by <name>, but are still locally available in
"remotes/<name>".
'update'::
Fetch updates for a named set of remotes in the repository as defined by
remotes.<group>. If a named group is not specified on the command line,
the configuration parameter remotes.default will get used; if
remotes.default is not defined, all remotes which do not the
configuration parameter remote.<name>.skipDefaultUpdate set to true will
be updated. (See gitlink:git-config[1]).
DISCUSSION

View File

@ -1,38 +0,0 @@
git-resolve(1)
==============
NAME
----
git-resolve - Merge two commits
SYNOPSIS
--------
'git-resolve' <current> <merged> <message>
DESCRIPTION
-----------
DEPRECATED and will be removed in 1.5.1. Use `git-merge` instead.
Given two commits and a merge message, merge the <merged> commit
into <current> commit, with the commit log message <message>.
When <current> is a descendant of <merged>, or <current> is an
ancestor of <merged>, no new commit is created and the <message>
is ignored. The former is informally called "already up to
date", and the latter is often called "fast forward".
Author
------
Written by Linus Torvalds <torvalds@osdl.org> and
Dan Holmsand <holmsand@gmail.com>.
Documentation
--------------
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
GIT
---
Part of the gitlink:git[7] suite

View File

@ -27,6 +27,7 @@ SYNOPSIS
[ \--pretty | \--header ]
[ \--bisect ]
[ \--merge ]
[ \--reverse ]
[ \--walk-reflogs ]
<commit>... [ \-- <paths>... ]
@ -266,6 +267,10 @@ By default, the commits are shown in reverse chronological order.
parent comes before all of its children, but otherwise things
are still ordered in the commit timestamp order.
--reverse::
Output the commits in reverse order.
Object Traversal
~~~~~~~~~~~~~~~~

View File

@ -190,6 +190,13 @@ blobs contained in a commit.
and dereference the tag recursively until a non-tag object is
found.
* A colon, followed by a slash, followed by a text: this names
a commit whose commit message starts with the specified text.
This name returns the youngest matching commit which is
reachable from any ref. If the commit message starts with a
'!', you have to repeat that; the special sequence ':/!',
followed by something else than '!' is reserved for now.
* A suffix ':' followed by a path; this names the blob or tree
at the given path in the tree-ish object named by the part
before the colon.

View File

@ -40,7 +40,8 @@ The --cc option must be repeated for each user you want on the cc list.
the first will be sent as replies to the first email sent. When using
this, it is recommended that the first file given be an overview of the
entire patch series.
Default is --chain-reply-to
Default is the value of the 'sendemail.chainreplyto' configuration
value; if that is unspecified, default to --chain-reply-to.
--compose::
Use $EDITOR to edit an introductory message for the
@ -59,7 +60,8 @@ The --cc option must be repeated for each user you want on the cc list.
is not set, this will be prompted for.
--no-signed-off-by-cc::
Do not add emails found in Signed-off-by: lines to the cc list.
Do not add emails found in Signed-off-by: or Cc: lines to the
cc list.
--quiet::
Make git-send-email less verbose. One line per email should be
@ -101,6 +103,13 @@ sendemail.aliasfiletype::
Format of the file(s) specified in sendemail.aliasesfile. Must be
one of 'mutt', 'mailrc', 'pine', or 'gnus'.
sendemail.bcc::
Email address (or alias) to always bcc.
sendemail.chainreplyto::
Boolean value specifying the default to the '--chain_reply_to'
parameter.
sendemail.smtpserver::
Default smtp server to use.

View File

@ -13,14 +13,13 @@ DESCRIPTION
-----------
git-svn is a simple conduit for changesets between Subversion and git.
It is not to be confused with gitlink:git-svnimport[1], which is
read-only and geared towards tracking multiple branches.
read-only.
git-svn was originally designed for an individual developer who wants a
bidirectional flow of changesets between a single branch in Subversion
and an arbitrary number of branches in git. Since its inception,
git-svn has gained the ability to track multiple branches in a manner
similar to git-svnimport; but it cannot (yet) automatically detect new
branches and tags like git-svnimport does.
similar to git-svnimport.
git-svn is especially useful when it comes to tracking repositories
not organized in the way Subversion developers recommend (trunk,
@ -31,26 +30,88 @@ COMMANDS
--
'init'::
Creates an empty git repository with additional metadata
directories for git-svn. The Subversion URL must be specified
as a command-line argument. Optionally, the target directory
to operate on can be specified as a second argument. Normally
this command initializes the current directory.
Initializes an empty git repository with additional
metadata directories for git-svn. The Subversion URL
may be specified as a command-line argument, or as full
URL arguments to -T/-t/-b. Optionally, the target
directory to operate on can be specified as a second
argument. Normally this command initializes the current
directory.
-T<trunk_subdir>::
--trunk=<trunk_subdir>::
-t<tags_subdir>::
--tags=<tags_subdir>::
-b<branches_subdir>::
--branches=<branches_subdir>::
These are optional command-line options for init. Each of
these flags can point to a relative repository path
(--tags=project/tags') or a full url
(--tags=https://foo.org/project/tags)
--no-metadata::
Set the 'noMetadata' option in the [svn-remote] config.
--use-svm-props::
Set the 'useSvmProps' option in the [svn-remote] config.
--use-svnsync-props::
Set the 'useSvnsyncProps' option in the [svn-remote] config.
--rewrite-root=<URL>::
Set the 'rewriteRoot' option in the [svn-remote] config.
--username=<USER>::
For transports that SVN handles authentication for (http,
https, and plain svn), specify the username. For other
transports (eg svn+ssh://), you must include the username in
the URL, eg svn+ssh://foo@svn.bar.com/project
--prefix=<prefix>::
This allows one to specify a prefix which is prepended
to the names of remotes if trunk/branches/tags are
specified. The prefix does not automatically include a
trailing slash, so be sure you include one in the
argument if that is what you want. This is useful if
you wish to track multiple projects that share a common
repository.
'fetch'::
Fetch unfetched revisions from the Subversion URL we are
tracking. refs/remotes/git-svn will be updated to the
latest revision.
Fetch unfetched revisions from the Subversion remote we are
tracking. The name of the [svn-remote "..."] section in the
.git/config file may be specified as an optional command-line
argument.
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 'dcommit'
command (see below) to write git commits back to
remotes/git-svn.
'clone'::
Runs 'init' and 'fetch'. It will automatically create a
directory based on the basename of the URL passed to it;
or if a second argument is passed; it will create a directory
and work within that. It accepts all arguments that the
'init' and 'fetch' commands accept; with the exception of
'--fetch-all'. After a repository is cloned, the 'fetch'
command will be able to update revisions without affecting
the working tree; and the 'rebase' command will be able
to update the working tree with the latest changes.
See '<<fetch-args,Additional Fetch Arguments>>' if you are interested in
manually joining branches on commit.
'rebase'::
This fetches revisions from the SVN parent of the current HEAD
and rebases the current (uncommitted to SVN) work against it.
This works similarly to 'svn update' or 'git-pull' except that
it preserves linear history with 'git-rebase' instead of
'git-merge' for ease of dcommit-ing with git-svn.
This accepts all options that 'git-svn fetch' and 'git-rebase'
accepts. However '--fetch-all' only fetches from the current
[svn-remote], and not all [svn-remote] definitions.
Like 'git-rebase'; this requires that the working tree be clean
and have no uncommitted changes.
+
--
-l;;
--local;;
Do not fetch remotely; only run 'git-rebase' against the
last fetched commit from the upstream SVN.
--
+
'dcommit'::
Commit each diff from a specified head directly to the SVN
@ -64,29 +125,40 @@ manually joining branches on commit.
alternative to HEAD.
This is advantageous over 'set-tree' (below) because it produces
cleaner, more linear history.
--
'log'::
This should make it easy to look up svn log messages when svn
users refer to -r/--revision numbers.
+
The following features from `svn log' are supported:
+
--
--revision=<n>[:<n>];;
is supported, non-numeric args are not:
HEAD, NEXT, BASE, PREV, etc ...
-v/--verbose;;
it's not completely compatible with the --verbose
output in svn log, but reasonably close.
--limit=<n>;;
is NOT the same as --max-count, doesn't count
merged/excluded commits
--incremental;;
supported
--
+
New features:
+
--
--show-commit;;
shows the git commit sha1, as well
--oneline;;
our version of --pretty=oneline
--
+
Any other arguments are passed directly to `git log'
The following features from `svn log' are supported:
--revision=<n>[:<n>] - is supported, non-numeric args are not:
HEAD, NEXT, BASE, PREV, etc ...
-v/--verbose - it's not completely compatible with
the --verbose output in svn log, but
reasonably close.
--limit=<n> - is NOT the same as --max-count,
doesn't count merged/excluded commits
--incremental - supported
New features:
--show-commit - shows the git commit sha1, as well
--oneline - our version of --pretty=oneline
Any other arguments are passed directly to `git log'
--
'set-tree'::
You should consider using 'dcommit' instead of this command.
Commit specified commit or tree objects to SVN. This relies on
@ -96,16 +168,6 @@ manually joining branches on commit.
commit. All merging is assumed to have taken place
independently of git-svn functions.
'rebuild'::
Not a part of daily usage, but this is a useful command if
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
resume fetch operations. A Subversion URL may be optionally
specified at the command-line if the directory/repository you're
tracking has moved or changed protocols.
'show-ignore'::
Recursively finds and lists the svn:ignore property on
directories. The output is suitable for appending to
@ -122,53 +184,13 @@ manually joining branches on commit.
repository (that has been init-ed with git-svn).
The -r<revision> option is required for this.
'graft-branches'::
This command attempts to detect merges/branches from already
imported history. Techniques used currently include regexes,
file copies, and tree-matches). This command generates (or
modifies) the $GIT_DIR/info/grafts file. This command is
considered experimental, and inherently flawed because
merge-tracking in SVN is inherently flawed and inconsistent
across different repositories.
'multi-init'::
This command supports git-svnimport-like command-line syntax for
importing repositories that are laid out as recommended by the
SVN folks. This is a bit more tolerant than the git-svnimport
command-line syntax and doesn't require the user to figure out
where the repository URL ends and where the repository path
begins.
-T<trunk_subdir>::
--trunk=<trunk_subdir>::
-t<tags_subdir>::
--tags=<tags_subdir>::
-b<branches_subdir>::
--branches=<branches_subdir>::
These are the command-line options for multi-init. Each of
these flags can point to a relative repository path
(--tags=project/tags') or a full url
(--tags=https://foo.org/project/tags)
--prefix=<prefix>
This allows one to specify a prefix which is prepended to the
names of remotes. The prefix does not automatically include a
trailing slash, so be sure you include one in the argument if
that is what you want. This is useful if you wish to track
multiple projects that share a common repository.
'multi-fetch'::
This runs fetch on all known SVN branches we're tracking. This
will NOT discover new branches (unlike git-svnimport), so
multi-init will need to be re-run (it's idempotent).
--
OPTIONS
-------
--
--shared::
--shared[={false|true|umask|group|all|world|everybody}]::
--template=<template_directory>::
Only used with the 'init' command.
These are passed directly to gitlink:git-init[1].
@ -176,14 +198,15 @@ OPTIONS
-r <ARG>::
--revision <ARG>::
Only used with the 'fetch' command.
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 allows revision ranges for partial/cauterized history
to be supported. $NUMBER, $NUMBER1:$NUMBER2 (numeric ranges),
$NUMBER:HEAD, and BASE:$NUMBER are all supported.
This can allow you to make partial mirrors when running fetch.
This can allow you to make partial mirrors when running fetch;
but is generally not recommended because history will be skipped
and lost.
-::
--stdin::
@ -252,16 +275,18 @@ config key: svn.authorsfile
Make git-svn less verbose.
--repack[=<n>]::
--repack-flags=<flags>
These should help keep disk usage sane for large fetches
with many revisions.
--repack-flags=<flags>::
--repack takes an optional argument for the number of revisions
to fetch before repacking. This defaults to repacking every
1000 commits fetched if no argument is specified.
These should help keep disk usage sane for large fetches
with many revisions.
--repack-flags are passed directly to gitlink:git-repack[1].
--repack takes an optional argument for the number of revisions
to fetch before repacking. This defaults to repacking every
1000 commits fetched if no argument is specified.
--repack-flags are passed directly to gitlink:git-repack[1].
[verse]
config key: svn.repack
config key: svn.repackflags
@ -270,7 +295,7 @@ config key: svn.repackflags
-s<strategy>::
--strategy=<strategy>::
These are only used with the 'dcommit' command.
These are only used with the 'dcommit' and 'rebase' commands.
Passed directly to git-rebase when using 'dcommit' if a
'git-reset' cannot be used (see dcommit).
@ -289,121 +314,121 @@ ADVANCED OPTIONS
----------------
--
-b<refname>::
--branch <refname>::
Used with 'fetch', 'dcommit' or 'set-tree'.
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_.
This option may be specified multiple times, once for each
branch.
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-repos,Tracking Multiple Repositories or Branches>>'
for more information on using GIT_SVN_ID.
This sets GIT_SVN_ID (instead of using the environment). This
allows the user to override the default refname to fetch from
when tracking a single URL. The 'log' and 'dcommit' commands
no longer require this switch as an argument.
-R<remote name>::
--svn-remote <remote name>::
Specify the [svn-remote "<remote name>"] section to use,
this allows SVN multiple repositories to be tracked.
Default: "svn"
--follow-parent::
This is especially helpful when we're tracking a directory
that has been moved around within the repository, or if we
started tracking a branch and never tracked the trunk it was
descended from.
descended from. This feature is enabled by default, use
--no-follow-parent to disable it.
config key: svn.followparent
--no-metadata::
This gets rid of the git-svn-id: lines at the end of every commit.
--
CONFIG FILE-ONLY OPTIONS
------------------------
--
With this, you lose the ability to use the rebuild command. If
you ever lose your .git/svn/git-svn/.rev_db file, you won't be
able to fetch again, either. This is fine for one-shot imports.
svn.noMetadata::
svn-remote.<name>.noMetadata::
The 'git-svn log' command will not work on repositories using this,
either.
This gets rid of the git-svn-id: lines at the end of every commit.
config key: svn.nometadata
If you lose your .git/svn/git-svn/.rev_db file, git-svn will not
be able to rebuild it and you won't be able to fetch again,
either. This is fine for one-shot imports.
The 'git-svn log' command will not work on repositories using
this, either. Using this conflicts with the 'useSvmProps'
option for (hopefully) obvious reasons.
svn.useSvmProps::
svn-remote.<name>.useSvmProps::
This allows git-svn to re-map repository URLs and UUIDs from
mirrors created using SVN::Mirror (or svk) for metadata.
If an SVN revision has a property, "svm:headrev", it is likely
that the revision was created by SVN::Mirror (also used by SVK).
The property contains a repository UUID and a revision. We want
to make it look like we are mirroring the original URL, so
introduce a helper function that returns the original identity
URL and UUID, and use it when generating metadata in commit
messages.
svn.useSvnsyncProps::
svn-remote.<name>.useSvnsyncprops::
Similar to the useSvmProps option; this is for users
of the svnsync(1) command distributed with SVN 1.4.x and
later.
svn-remote.<name>.rewriteRoot::
This allows users to create repositories from alternate
URLs. For example, an administrator could run git-svn on the
server locally (accessing via file://) but wish to distribute
the repository with a public http:// or svn:// URL in the
metadata so users of it will see the public URL.
Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps
options all affect the metadata generated and used by git-svn; they
*must* be set in the configuration file before any history is imported
and these settings should never be changed once they are set.
Additionally, only one of these four options can be used per-svn-remote
section because they affect the 'git-svn-id:' metadata line.
--
COMPATIBILITY OPTIONS
---------------------
--
--upgrade::
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.
--ignore-nodate::
Only used with the 'fetch' command.
By default git-svn will crash if it tries to import a revision
from SVN which has '(no date)' listed as the date of the revision.
This is repository corruption on SVN's part, plain and simple.
But sometimes you really need those revisions anyway.
If supplied git-svn will convert '(no date)' entries to the UNIX
epoch (midnight on Jan. 1, 1970). Yes, that's probably very wrong.
SVN was very wrong.
--
Basic Examples
~~~~~~~~~~~~~~
BASIC EXAMPLES
--------------
Tracking and contributing to a the trunk of a Subversion-managed project:
------------------------------------------------------------------------
# Initialize a repo (like git init):
git-svn init http://svn.foo.org/project/trunk
# Fetch remote revisions:
git-svn fetch
# Create your own branch to hack on:
git checkout -b my-branch remotes/git-svn
# Do some work, and then commit your new changes to SVN, as well as
# automatically updating your working HEAD:
# Clone a repo (like git clone):
git-svn clone http://svn.foo.org/project/trunk
# Enter the newly cloned directory:
cd trunk
# You should be on master branch, double-check with git-branch
git branch
# Do some work and commit locally to git:
git commit ...
# Something is committed to SVN, rebase your local changes against the
# latest changes in SVN:
git-svn rebase
# Now commit your changes (that were committed previously using git) to SVN,
# as well as automatically updating your working HEAD:
git-svn dcommit
# 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
------------------------------------------------------------------------
Tracking and contributing to an entire Subversion-managed project
(complete with a trunk, tags and branches):
See also:
'<<tracking-multiple-repos,Tracking Multiple Repositories or Branches>>'
------------------------------------------------------------------------
# Initialize a repo (like git init):
git-svn multi-init http://svn.foo.org/project \
-T trunk -b branches -t tags
# Fetch remote revisions:
git-svn multi-fetch
# Create your own branch of trunk to hack on:
git checkout -b my-trunk remotes/trunk
# Do some work, and then commit your new changes to SVN, as well as
# automatically updating your working HEAD:
git-svn dcommit -i trunk
# Something has been committed to trunk, rebase the latest into your branch:
git-svn multi-fetch && git rebase remotes/trunk
# Append svn:ignore settings of trunk to the default git exclude file:
git-svn show-ignore -i trunk >> .git/info/exclude
# Check for new branches and tags (no arguments are needed):
git-svn multi-init
# Clone a repo (like git clone):
git-svn clone http://svn.foo.org/project -T trunk -b branches -t tags
# View all branches and tags you have cloned:
git branch -r
# Reset your master to trunk (or any other branch, replacing 'trunk'
# with the appropriate name):
git reset --hard remotes/trunk
# You may only dcommit to one branch/tag/trunk at a time. The usage
# of dcommit/rebase/show-ignore should be the same as above.
------------------------------------------------------------------------
REBASE VS. PULL/MERGE
@ -416,7 +441,7 @@ pulled or merged from. This is because the author favored
If you use 'git-svn set-tree 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' or
use 'git-svn rebase' to update your work branch instead of 'git pull' or
'git merge'. 'pull/merge' can cause non-linear history to be flattened
when committing into SVN, which can lead to merge commits reversing
previous commits in SVN.
@ -426,67 +451,49 @@ DESIGN PHILOSOPHY
Merge tracking in Subversion is lacking and doing branched development
with Subversion is cumbersome as a result. git-svn does not do
automated merge/branch tracking by default and leaves it entirely up to
the user on the git side.
[[tracking-multiple-repos]]
TRACKING MULTIPLE REPOSITORIES OR BRANCHES
------------------------------------------
Because git-svn does not care about relationships between different
branches or directories in a Subversion repository, git-svn has a simple
hack to allow it to track an arbitrary number of related _or_ unrelated
SVN repositories via one git repository. Simply use the --id/-i flag or
set the GIT_SVN_ID environment variable to a name other other than
"git-svn" (the default) and git-svn will ignore the contents of the
$GIT_DIR/svn/git-svn directory and instead do all of its work in
$GIT_DIR/svn/$GIT_SVN_ID for that invocation. The interface branch will
be remotes/$GIT_SVN_ID, instead of remotes/git-svn. Any
remotes/$GIT_SVN_ID branch should never be modified by the user outside
of git-svn commands.
[[fetch-args]]
ADDITIONAL FETCH ARGUMENTS
--------------------------
This is for advanced users, most users should ignore this section.
Unfetched SVN revisions may be imported as children of existing commits
by specifying additional arguments to 'fetch'. Additional parents may
optionally be specified in the form of sha1 hex sums at the
command-line. Unfetched SVN revisions may also be tied to particular
git commits with the following syntax:
------------------------------------------------
svn_revision_number=git_commit_sha1
------------------------------------------------
This allows you to tie unfetched SVN revision 375 to your current HEAD:
------------------------------------------------
git-svn fetch 375=$(git-rev-parse HEAD)
------------------------------------------------
If you're tracking a directory that has moved, or otherwise been
branched or tagged off of another directory in the repository and you
care about the full history of the project, then you can use
the --follow-parent option.
------------------------------------------------
git-svn fetch --follow-parent
------------------------------------------------
the user on the git side. git-svn does however follow copy
history of the directory that it is tracking, however (much like
how 'svn log' works).
BUGS
----
We ignore all SVN properties except svn:executable. Too difficult to
map them since we rely heavily on git write-tree being _exactly_ the
same on both the SVN and git working trees and I prefer not to clutter
working trees with metadata files.
We ignore all SVN properties except svn:executable. Any unhandled
properties are logged to $GIT_DIR/svn/<refname>/unhandled.log
Renamed and copied directories are not detected by git and hence not
tracked when committing to SVN. I do not plan on adding support for
this as it's quite difficult and time-consuming to get working for all
the possible corner cases (git doesn't do it, either). Renamed and
copied files are fully supported if they're similar enough for git to
detect them.
the possible corner cases (git doesn't do it, either). Committing
renamed and copied files are fully supported if they're similar enough
for git to detect them.
CONFIGURATION
-------------
git-svn stores [svn-remote] configuration information in the
repository .git/config file. It is similar the core git
[remote] sections except 'fetch' keys do not accept glob
arguments; but they are instead handled by the 'branches'
and 'tags' keys. Since some SVN repositories are oddly
configured with multiple projects glob expansions such those
listed below are allowed:
------------------------------------------------------------------------
[svn-remote "project-a"]
url = http://server.org/svn
branches = branches/*/project-a:refs/remotes/project-a/branches/*
tags = tags/*/project-a:refs/remotes/project-a/tags/*
trunk = trunk/project-a:refs/remotes/project-a/trunk
------------------------------------------------------------------------
Keep in mind that the '*' (asterisk) wildcard of the local ref
(left of the ':') *must* be the farthest right path component;
however the remote wildcard may be anywhere as long as it's own
independent path componet (surrounded by '/' or EOL). This
type of configuration is not automatically created by 'init' and
should be manually entered with a text-editor or using
gitlink:git-config[1]
SEE ALSO
--------

View File

@ -295,6 +295,11 @@ in the index and the file mode on the filesystem if they differ only on
executable bit. On such an unfortunate filesystem, you may
need to use `git-update-index --chmod=`.
Quite similarly, if `core.symlinks` configuration variable is set
to 'false' (see gitlink:git-config[1]), symbolic links are checked out
as plain files, and this command does not modify a recorded file mode
from symbolic link to regular file.
The command looks at `core.ignorestat` configuration variable. See
'Using "assume unchanged" bit' section above.

View File

@ -8,7 +8,7 @@ git-upload-pack - Send objects packed back to git-fetch-pack
SYNOPSIS
--------
'git-upload-pack' <directory>
'git-upload-pack' [--strict] [--timeout=<n>] <directory>
DESCRIPTION
-----------
@ -23,6 +23,13 @@ repository. For push operations, see 'git-send-pack'.
OPTIONS
-------
\--strict::
Do not try <directory>/.git/ if <directory> is no git directory.
\--timeout=<n>::
Interrupt transfer after <n> seconds of inactivity.
<directory>::
The repository to sync from.

View File

@ -35,6 +35,20 @@ ifdef::stalenotes[]
You are reading the documentation for the latest version of git.
Documentation for older releases are available here:
* link:v1.5.0.6/git.html[documentation for release 1.5.0.6]
* link:v1.5.0.6/RelNotes-1.5.0.6.txt[release notes for 1.5.0.6]
* link:v1.5.0.5/RelNotes-1.5.0.5.txt[release notes for 1.5.0.5]
* link:v1.5.0.3/RelNotes-1.5.0.3.txt[release notes for 1.5.0.3]
* link:v1.5.0.2/RelNotes-1.5.0.2.txt[release notes for 1.5.0.2]
* link:v1.5.0.1/RelNotes-1.5.0.1.txt[release notes for 1.5.0.1]
* link:v1.5.0/RelNotes-1.5.0.txt[release notes for 1.5.0]
* link:v1.4.4.4/git.html[documentation for release 1.4.4.4]
* link:v1.3.3/git.html[documentation for release 1.3.3]

View File

@ -85,7 +85,7 @@ Fortunately I did not have to; what I have in the current branch
------------------------------------------------
$ git checkout master
$ git resolve master revert-c99 fast ;# this should be a fast forward
$ git merge revert-c99 ;# this should be a fast forward
Updating from 10d781b9caa4f71495c7b34963bef137216f86a8 to e3a693c...
cache.h | 8 ++++----
commit.c | 2 +-
@ -95,13 +95,6 @@ Updating from 10d781b9caa4f71495c7b34963bef137216f86a8 to e3a693c...
5 files changed, 8 insertions(+), 8 deletions(-)
------------------------------------------------
The 'fast' in the above 'git resolve' is not a magic. I knew this
'resolve' would result in a fast forward merge, and if not, there is
something very wrong (so I would do 'git reset' on the 'master' branch
and examine the situation). When a fast forward merge is done, the
message parameter to 'git resolve' is discarded, because no new commit
is created. You could have said 'junk' or 'nothing' there as well.
There is no need to redo the test at this point. We fast forwarded
and we know 'master' matches 'revert-c99' exactly. In fact:

View File

@ -0,0 +1,52 @@
How to use git-daemon
Git can be run in inetd mode and in stand alone mode. But all you want is
let a coworker pull from you, and therefore need to set up a git server
real quick, right?
Note that git-daemon is not really chatty at the moment, especially when
things do not go according to plan (e.g. a socket could not be bound).
Another word of warning: if you run
$ git ls-remote git://127.0.0.1/rule-the-world.git
and you see a message like
fatal: The remote end hung up unexpectedly
it only means that _something_ went wrong. To find out _what_ went wrong,
you have to ask the server. (Git refuses to be more precise for your
security only. Take off your shoes now. You have any coins in your pockets?
Sorry, not allowed -- who knows what you planned to do with them?)
With these two caveats, let's see an example:
$ git daemon --reuseaddr --verbose --base-path=/home/gitte/git \
--export-all -- /home/gitte/git/rule-the-world.git
(Of course, unless your user name is `gitte` _and_ your repository is in
~/rule-the-world.git, you have to adjust the paths. If your repository is
not bare, be aware that you have to type the path to the .git directory!)
This invocation tries to reuse the address if it is already taken
(this can save you some debugging, because otherwise killing and restarting
git-daemon could just silently fail to bind to a socket).
Also, it is (relatively) verbose when somebody actually connects to it.
It also sets the base path, which means that all the projects which can be
accessed using this daemon have to reside in or under that path.
The option `--export-all` just means that you _don't_ have to create a
file named `git-daemon-export-ok` in each exported repository. (Otherwise,
git-daemon would complain loudly, and refuse to cooperate.)
Last of all, the repository which should be exported is specified. It is
a good practice to put the paths after a "--" separator.
Now, test your daemon with
$ git ls-remote git://127.0.0.1/rule-the-world.git
If this does not work, find out why, and submit a patch to this document.

View File

@ -77,9 +77,53 @@ displayed in full, regardless of whether --abbrev or
true parent commits, without taking grafts nor history
simplification into account.
* 'format:'
+
The 'format:' format allows you to specify which information
you want to show. It works a little bit like printf format,
with the notable exception that you get a newline with '%n'
instead of '\n'.
E.g, 'format:"The author of %h was %an, %ar%nThe title was >>%s<<"'
would show something like this:
The author of fe6e0ee was Junio C Hamano, 23 hours ago
The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
The placeholders are:
- '%H': commit hash
- '%h': abbreviated commit hash
- '%T': tree hash
- '%t': abbreviated tree hash
- '%P': parent hashes
- '%p': abbreviated parent hashes
- '%an': author name
- '%ae': author email
- '%ad': author date
- '%aD': author date, RFC2822 style
- '%ar': author date, relative
- '%at': author date, UNIX timestamp
- '%cn': committer name
- '%ce': committer email
- '%cd': committer date
- '%cD': committer date, RFC2822 style
- '%cr': committer date, relative
- '%ct': committer date, UNIX timestamp
- '%e': encoding
- '%s': subject
- '%b': body
- '%Cred': switch color to red
- '%Cgreen': switch color to green
- '%Cblue': switch color to blue
- '%Creset': reset color
- '%n': newline
--encoding[=<encoding>]::
The commit objects record the encoding used for the log message
in their encoding header; this option can be used to tell the
command to re-code the commit log message in the encoding
preferred by the user. For non plumbing commands this
defaults to UTF-8.

View File

@ -0,0 +1,49 @@
Def.: Shallow commits do have parents, but not in the shallow
repo, and therefore grafts are introduced pretending that
these commits have no parents.
The basic idea is to write the SHA1s of shallow commits into
$GIT_DIR/shallow, and handle its contents like the contents
of $GIT_DIR/info/grafts (with the difference that shallow
cannot contain parent information).
This information is stored in a new file instead of grafts, or
even the config, since the user should not touch that file
at all (even throughout development of the shallow clone, it
was never manually edited!).
Each line contains exactly one SHA1. When read, a commit_graft
will be constructed, which has nr_parent < 0 to make it easier
to discern from user provided grafts.
Since fsck-objects relies on the library to read the objects,
it honours shallow commits automatically.
There are some unfinished ends of the whole shallow business:
- maybe we have to force non-thin packs when fetching into a
shallow repo (ATM they are forced non-thin).
- A special handling of a shallow upstream is needed. At some
stage, upload-pack has to check if it sends a shallow commit,
and it should send that information early (or fail, if the
client does not support shallow repositories). There is no
support at all for this in this patch series.
- Instead of locking $GIT_DIR/shallow at the start, just
the timestamp of it is noted, and when it comes to writing it,
a check is performed if the mtime is still the same, dying if
it is not.
- It is unclear how "push into/from a shallow repo" should behave.
- If you deepen a history, you'd want to get the tags of the
newly stored (but older!) commits. This does not work right now.
To make a shallow clone, you can call "git-clone --depth 20 repo".
The result contains only commit chains with a length of at most 20.
It also writes an appropriate $GIT_DIR/shallow.
You can deepen a shallow repository with "git-fetch --depth 20
repo branch", which will fetch branch from repo, but stop at depth
20, updating $GIT_DIR/shallow.

View File

@ -2869,7 +2869,7 @@ stages to temporary files and calls a "merge" script on it:
$ git-merge-index git-merge-one-file hello.c
-------------------------------------------------
and that is what higher level `git resolve` is implemented with.
and that is what higher level `git merge -s resolve` is implemented with.
How git stores objects efficiently: pack files
----------------------------------------------

View File

@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v1.5.0.6.GIT
DEF_VER=v1.5.1-rc3.GIT
LF='
'

132
Makefile
View File

@ -1,6 +1,8 @@
# The default target of this Makefile is...
all::
# Define V=1 to have a more verbose compile.
#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# This also implies MOZILLA_SHA1.
#
@ -131,6 +133,7 @@ prefix = $(HOME)
bindir = $(prefix)/bin
gitexecdir = $(bindir)
template_dir = $(prefix)/share/git-core/templates/
ETC_GITCONFIG = $(prefix)/etc/gitconfig
# DESTDIR=
# default configuration for gitweb
@ -174,12 +177,12 @@ BASIC_LDFLAGS =
SCRIPT_SH = \
git-bisect.sh git-checkout.sh \
git-clean.sh git-clone.sh git-commit.sh \
git-fetch.sh git-gc.sh \
git-fetch.sh \
git-ls-remote.sh \
git-merge-one-file.sh git-parse-remote.sh \
git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
git-pull.sh git-rebase.sh \
git-repack.sh git-request-pull.sh git-reset.sh \
git-resolve.sh git-revert.sh git-sh-setup.sh \
git-sh-setup.sh \
git-tag.sh git-verify-tag.sh \
git-applymbox.sh git-applypatch.sh git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
@ -195,7 +198,7 @@ SCRIPT_PERL = \
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
git-cherry-pick git-status git-instaweb
git-status git-instaweb
# ... and all the rest that could be moved out of bindir to gitexecdir
PROGRAMS = \
@ -222,7 +225,7 @@ EXTRA_PROGRAMS =
BUILT_INS = \
git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
git-get-tar-commit-id$X git-init$X git-repo-config$X \
git-fsck-objects$X \
git-fsck-objects$X git-cherry-pick$X \
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
# what 'all' will build and 'install' will install, in gitexecdir
@ -269,7 +272,8 @@ LIB_OBJS = \
revision.o pager.o tree-walk.o xdiff-interface.o \
write_or_die.o trace.o list-objects.o grep.o \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o
BUILTIN_OBJS = \
builtin-add.o \
@ -278,6 +282,7 @@ BUILTIN_OBJS = \
builtin-archive.o \
builtin-blame.o \
builtin-branch.o \
builtin-bundle.o \
builtin-cat-file.o \
builtin-checkout-index.o \
builtin-check-ref-format.o \
@ -287,11 +292,12 @@ BUILTIN_OBJS = \
builtin-diff.o \
builtin-diff-files.o \
builtin-diff-index.o \
builtin-diff-stages.o \
builtin-diff-tree.o \
builtin-fetch--tool.o \
builtin-fmt-merge-msg.o \
builtin-for-each-ref.o \
builtin-fsck.o \
builtin-gc.o \
builtin-grep.o \
builtin-init-db.o \
builtin-log.o \
@ -299,6 +305,7 @@ BUILTIN_OBJS = \
builtin-ls-tree.o \
builtin-mailinfo.o \
builtin-mailsplit.o \
builtin-merge-base.o \
builtin-merge-file.o \
builtin-mv.o \
builtin-name-rev.o \
@ -312,6 +319,7 @@ BUILTIN_OBJS = \
builtin-rerere.o \
builtin-rev-list.o \
builtin-rev-parse.o \
builtin-revert.o \
builtin-rm.o \
builtin-runstatus.o \
builtin-shortlog.o \
@ -600,9 +608,35 @@ ifdef NO_PERL_MAKEMAKER
export NO_PERL_MAKEMAKER
endif
QUIET_SUBDIR0 = $(MAKE) -C # space to separate -C and subdir
QUIET_SUBDIR1 =
ifneq ($(findstring $(MAKEFLAGS),w),w)
PRINT_DIR = --no-print-directory
else # "make -w"
NO_SUBDIR = :
endif
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
QUIET_CC = @echo ' ' CC $@;
QUIET_AR = @echo ' ' AR $@;
QUIET_LINK = @echo ' ' LINK $@;
QUIET_BUILT_IN = @echo ' ' BUILTIN $@;
QUIET_GEN = @echo ' ' GEN $@;
QUIET_SUBDIR0 = @subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
$(MAKE) $(PRINT_DIR) -C $$subdir
export V
export QUIET_GEN
export QUIET_BUILT_IN
endif
endif
# Shell quote (do not use $(call) to accommodate ancient setups);
SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG))
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
bindir_SQ = $(subst ','\'',$(bindir))
@ -615,7 +649,8 @@ PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
LIBS = $(GITLIBS) $(EXTLIBS)
BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' $(COMPAT_CFLAGS)
BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
-DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' $(COMPAT_CFLAGS)
LIB_OBJS += $(COMPAT_OBJS)
ALL_CFLAGS += $(BASIC_CFLAGS)
@ -632,44 +667,43 @@ ifneq (,$X)
endif
all::
$(MAKE) -C git-gui all
$(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
$(MAKE) -C templates
$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS
$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
$(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
help.o: common-cmds.h
$(BUILT_INS): git$X
rm -f $@ && ln git$X $@
$(QUIET_BUILT_IN)rm -f $@ && ln git$X $@
common-cmds.h: Documentation/git-*.txt
./generate-cmdlist.sh > $@+
mv $@+ $@
$(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
rm -f $@ $@+
$(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
$@.sh >$@+
chmod +x $@+
$@.sh >$@+ && \
chmod +x $@+ && \
mv $@+ $@
$(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
perl/perl.mak: GIT-CFLAGS
$(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
$(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
rm -f $@ $@+
$(QUIET_GEN)rm -f $@ $@+ && \
INSTLIBDIR=`$(MAKE) -C perl -s --no-print-directory instlibdir` && \
sed -e '1{' \
-e ' s|#!.*perl|#!$(PERL_PATH_SQ)|' \
@ -680,20 +714,15 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
-e '}' \
-e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
$@.perl >$@+
chmod +x $@+
mv $@+ $@
git-cherry-pick: git-revert
cp $< $@+
$@.perl >$@+ && \
chmod +x $@+ && \
mv $@+ $@
git-status: git-commit
cp $< $@+
mv $@+ $@
$(QUIET_GEN)cp $< $@+ && mv $@+ $@
gitweb/gitweb.cgi: gitweb/gitweb.perl
rm -f $@ $@+
$(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
-e 's|++GIT_BINDIR++|$(bindir)|g' \
@ -711,12 +740,12 @@ gitweb/gitweb.cgi: gitweb/gitweb.perl
-e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
-e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
-e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
$< >$@+
chmod +x $@+
$< >$@+ && \
chmod +x $@+ && \
mv $@+ $@
git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
rm -f $@ $@+
$(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
@ -724,15 +753,15 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
-e '/@@GITWEB_CGI@@/d' \
-e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \
-e '/@@GITWEB_CSS@@/d' \
$@.sh > $@+
chmod +x $@+
$@.sh > $@+ && \
chmod +x $@+ && \
mv $@+ $@
configure: configure.ac
rm -f $@ $<+
$(QUIET_GEN)rm -f $@ $<+ && \
sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
$< > $<+
autoconf -o $@ $<+
$< > $<+ && \
autoconf -o $@ $<+ && \
rm -f $<+
# These can record GIT_VERSION
@ -742,25 +771,25 @@ git$X git.spec \
: GIT-VERSION-FILE
%.o: %.c GIT-CFLAGS
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
%.o: %.S
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
exec_cmd.o: exec_cmd.c GIT-CFLAGS
$(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
http.o: http.c GIT-CFLAGS
$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
ifdef NO_EXPAT
http-fetch.o: http-fetch.c http.h GIT-CFLAGS
$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
endif
git-%$X: %.o $(GITLIBS)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
ssh-pull.o: ssh-fetch.c
ssh-push.o: ssh-upload.c
@ -774,11 +803,11 @@ git-imap-send$X: imap-send.o $(LIB_FILE)
http.o http-fetch.o http-push.o: http.h
git-http-fetch$X: fetch.o http.o http-fetch.o $(GITLIBS)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
$(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H)
@ -786,7 +815,7 @@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
$(DIFF_OBJS): diffcore.h
$(LIB_FILE): $(LIB_OBJS)
rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
$(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
xdiff/xmerge.o
@ -794,7 +823,7 @@ $(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
$(XDIFF_LIB): $(XDIFF_OBJS)
rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
$(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
perl/Makefile: perl/Git.pm perl/Makefile.PL GIT-CFLAGS
@ -831,7 +860,7 @@ GIT-CFLAGS: .FORCE-GIT-CFLAGS
export NO_SVN_TESTS
test: all
test: all test-chmtime$X
$(MAKE) -C t/ all
test-date$X: test-date.c date.o ctype.o
@ -846,6 +875,9 @@ test-dump-cache-tree$X: dump-cache-tree.o $(GITLIBS)
test-sha1$X: test-sha1.o $(GITLIBS)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
test-chmtime$X: test-chmtime.c
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $<
check-sha1:: test-sha1$X
./test-sha1.sh
@ -931,7 +963,7 @@ dist-doc:
clean:
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \
$(LIB_FILE) $(XDIFF_LIB)
test-chmtime$X $(LIB_FILE) $(XDIFF_LIB)
rm -f $(ALL_PROGRAMS) $(BUILT_INS) git$X
rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags
rm -rf autom4te.cache

6
README
View File

@ -38,3 +38,9 @@ requests, comments and patches to git@vger.kernel.org. To subscribe
to the list, send an email with just "subscribe git" in the body to
majordomo@vger.kernel.org. The mailing list archives are available at
http://marc.theaimsgroup.com/?l=git and other archival sites.
The messages titled "A note from the maintainer", "What's in
git.git (stable)" and "What's cooking in git.git (topics)" and
the discussion following them on the mailing list give a good
reference for project status, development direction and
remaining tasks.

View File

@ -1 +1 @@
Documentation/RelNotes-1.5.0.6.txt
Documentation/RelNotes-1.5.1.txt

View File

@ -262,7 +262,7 @@ static int write_tar_entry(const unsigned char *sha1,
static struct strbuf path;
int filenamelen = strlen(filename);
void *buffer;
char type[20];
enum object_type type;
unsigned long size;
if (!path.alloc) {
@ -283,7 +283,7 @@ static int write_tar_entry(const unsigned char *sha1,
buffer = NULL;
size = 0;
} else {
buffer = read_sha1_file(sha1, type, &size);
buffer = read_sha1_file(sha1, &type, &size);
if (!buffer)
die("cannot read %s", sha1_to_hex(sha1));
}

View File

@ -167,7 +167,7 @@ static int write_zip_entry(const unsigned char *sha1,
int pathlen;
unsigned char *out;
char *path;
char type[20];
enum object_type type;
void *buffer = NULL;
void *deflated = NULL;
@ -195,7 +195,7 @@ static int write_zip_entry(const unsigned char *sha1,
if (S_ISREG(mode) && zlib_compression_level != 0)
method = 8;
result = 0;
buffer = read_sha1_file(sha1, type, &size);
buffer = read_sha1_file(sha1, &type, &size);
if (!buffer)
die("cannot read %s", sha1_to_hex(sha1));
crc = crc32(crc, buffer, size);

6
blob.c
View File

@ -30,18 +30,18 @@ int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
int parse_blob(struct blob *item)
{
char type[20];
enum object_type type;
void *buffer;
unsigned long size;
int ret;
if (item->object.parsed)
return 0;
buffer = read_sha1_file(item->object.sha1, type, &size);
buffer = read_sha1_file(item->object.sha1, &type, &size);
if (!buffer)
return error("Could not read %s",
sha1_to_hex(item->object.sha1));
if (strcmp(type, blob_type))
if (type != OBJ_BLOB)
return error("Object %s not a blob",
sha1_to_hex(item->object.sha1));
ret = parse_blob_buffer(item, buffer, size);

View File

@ -12,6 +12,8 @@
static const char builtin_add_usage[] =
"git-add [-n] [-v] [-f] [--interactive | -i] [--] <filepattern>...";
static const char *excludes_file;
static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
{
char *seen;
@ -67,6 +69,8 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec)
path = git_path("info/exclude");
if (!access(path, R_OK))
add_excludes_from_file(dir, path);
if (!access(excludes_file, R_OK))
add_excludes_from_file(dir, excludes_file);
/*
* Calculate common prefix for the pathspec, and
@ -88,6 +92,18 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec)
prune_directory(dir, pathspec, baselen);
}
static int git_add_config(const char *var, const char *value)
{
if (!strcmp(var, "core.excludesfile")) {
if (!value)
die("core.excludesfile without value");
excludes_file = xstrdup(value);
return 0;
}
return git_default_config(var, value);
}
static struct lock_file lock_file;
static const char ignore_warning[] =
@ -115,7 +131,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
exit(1);
}
git_config(git_default_config);
git_config(git_add_config);
newfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);

View File

@ -28,6 +28,7 @@ static int newfd = -1;
static int unidiff_zero;
static int p_value = 1;
static int p_value_known;
static int check_index;
static int write_index;
static int cached;
@ -144,6 +145,7 @@ struct patch {
unsigned long deflate_origlen;
int lines_added, lines_deleted;
int score;
unsigned int is_toplevel_relative:1;
unsigned int inaccurate_eof:1;
unsigned int is_binary:1;
unsigned int is_copy:1;
@ -238,7 +240,7 @@ static int name_terminate(const char *name, int namelen, int c, int terminate)
return 1;
}
static char * find_name(const char *line, char *def, int p_value, int terminate)
static char *find_name(const char *line, char *def, int p_value, int terminate)
{
int len;
const char *start = line;
@ -311,11 +313,54 @@ static char * find_name(const char *line, char *def, int p_value, int terminate)
return name;
}
static int count_slashes(const char *cp)
{
int cnt = 0;
char ch;
while ((ch = *cp++))
if (ch == '/')
cnt++;
return cnt;
}
/*
* Given the string after "--- " or "+++ ", guess the appropriate
* p_value for the given patch.
*/
static int guess_p_value(const char *nameline)
{
char *name, *cp;
int val = -1;
if (is_dev_null(nameline))
return -1;
name = find_name(nameline, NULL, 0, TERM_SPACE | TERM_TAB);
if (!name)
return -1;
cp = strchr(name, '/');
if (!cp)
val = 0;
else if (prefix) {
/*
* Does it begin with "a/$our-prefix" and such? Then this is
* very likely to apply to our directory.
*/
if (!strncmp(name, prefix, prefix_length))
val = count_slashes(prefix);
else {
cp++;
if (!strncmp(cp, prefix, prefix_length))
val = count_slashes(prefix) + 1;
}
}
free(name);
return val;
}
/*
* Get the name etc info from the --/+++ lines of a traditional patch header
*
* NOTE! This hardcodes "-p1" behaviour in filename detection.
*
* FIXME! The end-of-filename heuristics are kind of screwy. For existing
* files, we can happily check the index for a match, but for creating a
* new file we should try to match whatever "patch" does. I have no idea.
@ -326,6 +371,16 @@ static void parse_traditional_patch(const char *first, const char *second, struc
first += 4; /* skip "--- " */
second += 4; /* skip "+++ " */
if (!p_value_known) {
int p, q;
p = guess_p_value(first);
q = guess_p_value(second);
if (p < 0) p = q;
if (0 <= p && p == q) {
p_value = p;
p_value_known = 1;
}
}
if (is_dev_null(first)) {
patch->is_new = 1;
patch->is_delete = 0;
@ -787,6 +842,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
{
unsigned long offset, len;
patch->is_toplevel_relative = 0;
patch->is_rename = patch->is_copy = 0;
patch->is_new = patch->is_delete = -1;
patch->old_mode = patch->new_mode = 0;
@ -831,6 +887,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
die("git diff header lacks filename information (line %d)", linenr);
patch->old_name = patch->new_name = patch->def_name;
}
patch->is_toplevel_relative = 1;
*hdrsize = git_hdr_len;
return offset;
}
@ -1129,11 +1186,11 @@ static struct fragment *parse_binary_hunk(char **buf_p,
*status_p = 0;
if (!strncmp(buffer, "delta ", 6)) {
if (!prefixcmp(buffer, "delta ")) {
patch_method = BINARY_DELTA_DEFLATED;
origlen = strtoul(buffer + 6, NULL, 10);
}
else if (!strncmp(buffer, "literal ", 8)) {
else if (!prefixcmp(buffer, "literal ")) {
patch_method = BINARY_LITERAL_DEFLATED;
origlen = strtoul(buffer + 8, NULL, 10);
}
@ -1393,28 +1450,39 @@ static void show_stats(struct patch *patch)
free(qname);
}
static int read_old_data(struct stat *st, const char *path, void *buf, unsigned long size)
static int read_old_data(struct stat *st, const char *path, char **buf_p, unsigned long *alloc_p, unsigned long *size_p)
{
int fd;
unsigned long got;
unsigned long nsize;
char *nbuf;
unsigned long size = *size_p;
char *buf = *buf_p;
switch (st->st_mode & S_IFMT) {
case S_IFLNK:
return readlink(path, buf, size);
return readlink(path, buf, size) != size;
case S_IFREG:
fd = open(path, O_RDONLY);
if (fd < 0)
return error("unable to open %s", path);
got = 0;
for (;;) {
int ret = xread(fd, (char *) buf + got, size - got);
int ret = xread(fd, buf + got, size - got);
if (ret <= 0)
break;
got += ret;
}
close(fd);
return got;
nsize = got;
nbuf = buf;
if (convert_to_git(path, &nbuf, &nsize)) {
free(buf);
*buf_p = nbuf;
*alloc_p = nsize;
*size_p = nsize;
}
return got != size;
default:
return -1;
}
@ -1656,6 +1724,8 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
/* Ignore it, we already handled it */
break;
default:
if (apply_verbosely)
error("invalid start of line: '%c'", first);
return -1;
}
patch += len;
@ -1753,6 +1823,9 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
}
}
if (offset && apply_verbosely)
error("while searching for:\n%.*s", oldsize, oldlines);
free(old);
free(new);
return offset;
@ -1839,11 +1912,11 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)
if (has_sha1_file(sha1)) {
/* We already have the postimage */
char type[10];
enum object_type type;
unsigned long size;
free(desc->buffer);
desc->buffer = read_sha1_file(sha1, type, &size);
desc->buffer = read_sha1_file(sha1, &type, &size);
if (!desc->buffer)
return error("the necessary postimage %s for "
"'%s' cannot be read",
@ -1899,8 +1972,8 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
buf = NULL;
if (cached) {
if (ce) {
char type[20];
buf = read_sha1_file(ce->sha1, type, &size);
enum object_type type;
buf = read_sha1_file(ce->sha1, &type, &size);
if (!buf)
return error("read of %s failed",
patch->old_name);
@ -1908,10 +1981,10 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
}
}
else if (patch->old_name) {
size = st->st_size;
size = xsize_t(st->st_size);
alloc = size + 8192;
buf = xmalloc(alloc);
if (read_old_data(st, patch->old_name, buf, alloc) != size)
if (read_old_data(st, patch->old_name, &buf, &alloc, &size))
return error("read of %s failed", patch->old_name);
}
@ -2233,7 +2306,7 @@ static void patch_stats(struct patch *patch)
}
}
static void remove_file(struct patch *patch)
static void remove_file(struct patch *patch, int rmdir_empty)
{
if (write_index) {
if (remove_file_from_cache(patch->old_name) < 0)
@ -2241,7 +2314,7 @@ static void remove_file(struct patch *patch)
cache_tree_invalidate_path(active_cache_tree, patch->old_name);
}
if (!cached) {
if (!unlink(patch->old_name)) {
if (!unlink(patch->old_name) && rmdir_empty) {
char *name = xstrdup(patch->old_name);
char *end = strrchr(name, '/');
while (end) {
@ -2282,16 +2355,27 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
{
int fd;
int fd, converted;
char *nbuf;
unsigned long nsize;
if (S_ISLNK(mode))
if (has_symlinks && S_ISLNK(mode))
/* Although buf:size is counted string, it also is NUL
* terminated.
*/
return symlink(buf, path);
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
if (fd < 0)
return -1;
nsize = size;
nbuf = (char *) buf;
converted = convert_to_working_tree(path, &nbuf, &nsize);
if (converted) {
buf = nbuf;
size = nsize;
}
while (size) {
int written = xwrite(fd, buf, size);
if (written < 0)
@ -2303,6 +2387,8 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
}
if (close(fd) < 0)
die("closing file %s: %s", path, strerror(errno));
if (converted)
free(nbuf);
return 0;
}
@ -2374,7 +2460,7 @@ static void write_out_one_result(struct patch *patch, int phase)
{
if (patch->is_delete > 0) {
if (phase == 0)
remove_file(patch);
remove_file(patch, 1);
return;
}
if (patch->is_new > 0 || patch->is_copy) {
@ -2387,7 +2473,7 @@ static void write_out_one_result(struct patch *patch, int phase)
* thing: remove the old, write the new
*/
if (phase == 0)
remove_file(patch);
remove_file(patch, 0);
if (phase == 1)
create_file(patch);
}
@ -2509,6 +2595,32 @@ static int use_patch(struct patch *p)
return 1;
}
static void prefix_one(char **name)
{
char *old_name = *name;
if (!old_name)
return;
*name = xstrdup(prefix_filename(prefix, prefix_length, *name));
free(old_name);
}
static void prefix_patches(struct patch *p)
{
if (!prefix || p->is_toplevel_relative)
return;
for ( ; p; p = p->next) {
if (p->new_name == p->old_name) {
char *prefixed = p->new_name;
prefix_one(&prefixed);
p->new_name = p->old_name = prefixed;
}
else {
prefix_one(&p->new_name);
prefix_one(&p->old_name);
}
}
}
static int apply_patch(int fd, const char *filename, int inaccurate_eof)
{
unsigned long offset, size;
@ -2531,11 +2643,14 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
break;
if (apply_in_reverse)
reverse_patches(patch);
if (prefix)
prefix_patches(patch);
if (use_patch(patch)) {
patch_stats(patch);
*listp = patch;
listp = &patch->next;
} else {
}
else {
/* perhaps free it a bit better? */
free(patch);
skipped_patch++;
@ -2596,9 +2711,16 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
int read_stdin = 1;
int inaccurate_eof = 0;
int errs = 0;
int is_not_gitdir = 0;
const char *whitespace_option = NULL;
prefix = setup_git_directory_gently(&is_not_gitdir);
prefix_length = prefix ? strlen(prefix) : 0;
git_config(git_apply_config);
if (apply_default_whitespace)
parse_whitespace_option(apply_default_whitespace);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
char *end;
@ -2609,15 +2731,16 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
read_stdin = 0;
continue;
}
if (!strncmp(arg, "--exclude=", 10)) {
if (!prefixcmp(arg, "--exclude=")) {
struct excludes *x = xmalloc(sizeof(*x));
x->path = arg + 10;
x->next = excludes;
excludes = x;
continue;
}
if (!strncmp(arg, "-p", 2)) {
if (!prefixcmp(arg, "-p")) {
p_value = atoi(arg + 2);
p_value_known = 1;
continue;
}
if (!strcmp(arg, "--no-add")) {
@ -2649,10 +2772,14 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
continue;
}
if (!strcmp(arg, "--index")) {
if (is_not_gitdir)
die("--index outside a repository");
check_index = 1;
continue;
}
if (!strcmp(arg, "--cached")) {
if (is_not_gitdir)
die("--cached outside a repository");
check_index = 1;
cached = 1;
continue;
@ -2670,13 +2797,13 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
line_termination = 0;
continue;
}
if (!strncmp(arg, "-C", 2)) {
if (!prefixcmp(arg, "-C")) {
p_context = strtoul(arg + 2, &end, 0);
if (*end != '\0')
die("unrecognized context count '%s'", arg + 2);
continue;
}
if (!strncmp(arg, "--whitespace=", 13)) {
if (!prefixcmp(arg, "--whitespace=")) {
whitespace_option = arg + 13;
parse_whitespace_option(arg + 13);
continue;
@ -2693,7 +2820,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
apply = apply_with_reject = apply_verbosely = 1;
continue;
}
if (!strcmp(arg, "--verbose")) {
if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) {
apply_verbosely = 1;
continue;
}
@ -2701,14 +2828,6 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
inaccurate_eof = 1;
continue;
}
if (check_index && prefix_length < 0) {
prefix = setup_git_directory();
prefix_length = prefix ? strlen(prefix) : 0;
git_config(git_apply_config);
if (!whitespace_option && apply_default_whitespace)
parse_whitespace_option(apply_default_whitespace);
}
if (0 < prefix_length)
arg = prefix_filename(prefix, prefix_length, arg);

View File

@ -35,7 +35,7 @@ static int run_remote_archiver(const char *remote, int argc,
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strncmp("--exec=", arg, 7)) {
if (!prefixcmp(arg, "--exec=")) {
if (exec_at)
die("multiple --exec specified");
exec = arg + 7;
@ -62,7 +62,7 @@ static int run_remote_archiver(const char *remote, int argc,
if (buf[len-1] == '\n')
buf[--len] = 0;
if (strcmp(buf, "ACK")) {
if (len > 5 && !strncmp(buf, "NACK ", 5))
if (len > 5 && !prefixcmp(buf, "NACK "))
die("git-archive: NACK %s", buf + 5);
die("git-archive: protocol error");
}
@ -166,11 +166,11 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar)
verbose = 1;
continue;
}
if (!strncmp(arg, "--format=", 9)) {
if (!prefixcmp(arg, "--format=")) {
format = arg + 9;
continue;
}
if (!strncmp(arg, "--prefix=", 9)) {
if (!prefixcmp(arg, "--prefix=")) {
base = arg + 9;
continue;
}
@ -218,7 +218,7 @@ static const char *extract_remote_arg(int *ac, const char **av)
if (!strcmp(arg, "--"))
no_more_options = 1;
if (!no_more_options) {
if (!strncmp(arg, "--remote=", 9)) {
if (!prefixcmp(arg, "--remote=")) {
if (remote)
die("Multiple --remote specified");
remote = arg + 9;

View File

@ -87,9 +87,9 @@ struct origin {
static char *fill_origin_blob(struct origin *o, mmfile_t *file)
{
if (!o->file.ptr) {
char type[10];
enum object_type type;
num_read_blob++;
file->ptr = read_sha1_file(o->blob_sha1, type,
file->ptr = read_sha1_file(o->blob_sha1, &type,
(unsigned long *)(&(file->size)));
o->file = *file;
}
@ -180,16 +180,15 @@ struct scoreboard {
int *lineno;
};
static int cmp_suspect(struct origin *a, struct origin *b)
static inline int same_suspect(struct origin *a, struct origin *b)
{
int cmp = hashcmp(a->commit->object.sha1, b->commit->object.sha1);
if (cmp)
return cmp;
return strcmp(a->path, b->path);
if (a == b)
return 1;
if (a->commit != b->commit)
return 0;
return !strcmp(a->path, b->path);
}
#define cmp_suspect(a, b) ( ((a)==(b)) ? 0 : cmp_suspect(a,b) )
static void sanity_check_refcnt(struct scoreboard *);
/*
@ -202,7 +201,7 @@ static void coalesce(struct scoreboard *sb)
struct blame_entry *ent, *next;
for (ent = sb->ent; ent && (next = ent->next); ent = next) {
if (!cmp_suspect(ent->suspect, next->suspect) &&
if (same_suspect(ent->suspect, next->suspect) &&
ent->guilty == next->guilty &&
ent->s_lno + ent->num_lines == next->s_lno) {
ent->num_lines += next->num_lines;
@ -263,7 +262,6 @@ static struct origin *get_origin(struct scoreboard *sb,
static int fill_blob_sha1(struct origin *origin)
{
unsigned mode;
char type[10];
if (!is_null_sha1(origin->blob_sha1))
return 0;
@ -271,8 +269,7 @@ static int fill_blob_sha1(struct origin *origin)
origin->path,
origin->blob_sha1, &mode))
goto error_out;
if (sha1_object_info(origin->blob_sha1, type, NULL) ||
strcmp(type, blob_type))
if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB)
goto error_out;
return 0;
error_out:
@ -777,7 +774,7 @@ static int find_last_in_target(struct scoreboard *sb, struct origin *target)
int last_in_target = -1;
for (e = sb->ent; e; e = e->next) {
if (e->guilty || cmp_suspect(e->suspect, target))
if (e->guilty || !same_suspect(e->suspect, target))
continue;
if (last_in_target < e->s_lno + e->num_lines)
last_in_target = e->s_lno + e->num_lines;
@ -797,7 +794,7 @@ static void blame_chunk(struct scoreboard *sb,
struct blame_entry *e;
for (e = sb->ent; e; e = e->next) {
if (e->guilty || cmp_suspect(e->suspect, target))
if (e->guilty || !same_suspect(e->suspect, target))
continue;
if (same <= e->s_lno)
continue;
@ -972,7 +969,7 @@ static int find_move_in_parent(struct scoreboard *sb,
while (made_progress) {
made_progress = 0;
for (e = sb->ent; e; e = e->next) {
if (e->guilty || cmp_suspect(e->suspect, target))
if (e->guilty || !same_suspect(e->suspect, target))
continue;
find_copy_in_blob(sb, e, parent, split, &file_p);
if (split[1].suspect &&
@ -1004,12 +1001,12 @@ static struct blame_list *setup_blame_list(struct scoreboard *sb,
struct blame_list *blame_list = NULL;
for (e = sb->ent, num_ents = 0; e; e = e->next)
if (!e->guilty && !cmp_suspect(e->suspect, target))
if (!e->guilty && same_suspect(e->suspect, target))
num_ents++;
if (num_ents) {
blame_list = xcalloc(num_ents, sizeof(struct blame_list));
for (e = sb->ent, i = 0; e; e = e->next)
if (!e->guilty && !cmp_suspect(e->suspect, target))
if (!e->guilty && same_suspect(e->suspect, target))
blame_list[i++].ent = e;
}
*num_ents_p = num_ents;
@ -1139,7 +1136,7 @@ static void pass_whole_blame(struct scoreboard *sb,
origin->file.ptr = NULL;
}
for (e = sb->ent; e; e = e->next) {
if (cmp_suspect(e->suspect, origin))
if (!same_suspect(e->suspect, origin))
continue;
origin_incref(porigin);
origin_decref(e->suspect);
@ -1246,26 +1243,26 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
*/
struct commit_info
{
char *author;
char *author_mail;
const char *author;
const char *author_mail;
unsigned long author_time;
char *author_tz;
const char *author_tz;
/* filled only when asked for details */
char *committer;
char *committer_mail;
const char *committer;
const char *committer_mail;
unsigned long committer_time;
char *committer_tz;
const char *committer_tz;
char *summary;
const char *summary;
};
/*
* Parse author/committer line in the commit object buffer
*/
static void get_ac_line(const char *inbuf, const char *what,
int bufsz, char *person, char **mail,
unsigned long *time, char **tz)
int bufsz, char *person, const char **mail,
unsigned long *time, const char **tz)
{
int len;
char *tmp, *endp;
@ -1282,7 +1279,7 @@ static void get_ac_line(const char *inbuf, const char *what,
if (bufsz <= len) {
error_out:
/* Ugh */
person = *mail = *tz = "(unknown)";
*mail = *tz = "(unknown)";
*time = 0;
return;
}
@ -1322,10 +1319,10 @@ static void get_commit_info(struct commit *commit,
* we now need to populate them for output.
*/
if (!commit->buffer) {
char type[20];
enum object_type type;
unsigned long size;
commit->buffer =
read_sha1_file(commit->object.sha1, type, &size);
read_sha1_file(commit->object.sha1, &type, &size);
}
ret->author = author_buf;
get_ac_line(commit->buffer, "\nauthor ",
@ -1445,7 +1442,7 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
/* Take responsibility for the remaining entries */
for (ent = sb->ent; ent; ent = ent->next)
if (!cmp_suspect(ent->suspect, suspect))
if (same_suspect(ent->suspect, suspect))
found_guilty_entry(ent);
origin_decref(suspect);
@ -1965,7 +1962,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
die("Cannot lstat %s", path);
read_from = path;
}
fin_size = st.st_size;
fin_size = xsize_t(st.st_size);
buf = xmalloc(fin_size+1);
mode = canon_mode(st.st_mode);
switch (st.st_mode & S_IFMT) {
@ -2006,7 +2003,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
buf[fin_size] = 0;
origin->file.ptr = buf;
origin->file.size = fin_size;
pretend_sha1_file(buf, fin_size, blob_type, origin->blob_sha1);
pretend_sha1_file(buf, fin_size, OBJ_BLOB, origin->blob_sha1);
commit->util = origin;
/*
@ -2065,9 +2062,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
int i, seen_dashdash, unk, opt;
long bottom, top, lno;
int output_option = 0;
int show_stats = 0;
const char *revs_file = NULL;
const char *final_commit_name = NULL;
char type[10];
enum object_type type;
const char *bottomtop = NULL;
const char *contents_from = NULL;
@ -2086,6 +2084,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
blank_boundary = 1;
else if (!strcmp("--root", arg))
show_root = 1;
else if (!strcmp(arg, "--show-stats"))
show_stats = 1;
else if (!strcmp("-c", arg))
output_option |= OUTPUT_ANNOTATE_COMPAT;
else if (!strcmp("-t", arg))
@ -2094,17 +2094,17 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
output_option |= OUTPUT_LONG_OBJECT_NAME;
else if (!strcmp("-S", arg) && ++i < argc)
revs_file = argv[i];
else if (!strncmp("-M", arg, 2)) {
else if (!prefixcmp(arg, "-M")) {
opt |= PICKAXE_BLAME_MOVE;
blame_move_score = parse_score(arg+2);
}
else if (!strncmp("-C", arg, 2)) {
else if (!prefixcmp(arg, "-C")) {
if (opt & PICKAXE_BLAME_COPY)
opt |= PICKAXE_BLAME_COPY_HARDER;
opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
blame_copy_score = parse_score(arg+2);
}
else if (!strncmp("-L", arg, 2)) {
else if (!prefixcmp(arg, "-L")) {
if (!arg[2]) {
if (++i >= argc)
usage(blame_usage);
@ -2299,7 +2299,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
if (fill_blob_sha1(o))
die("no such path %s in %s", path, final_commit_name);
sb.final_buf = read_sha1_file(o->blob_sha1, type,
sb.final_buf = read_sha1_file(o->blob_sha1, &type,
&sb.final_buf_size);
}
num_read_blob++;
@ -2351,7 +2351,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
ent = e;
}
if (DEBUG) {
if (show_stats) {
printf("num read blob: %d\n", num_read_blob);
printf("num get patch: %d\n", num_get_patch);
printf("num commits: %d\n", num_commits);

View File

@ -12,7 +12,7 @@
#include "builtin.h"
static const char builtin_branch_usage[] =
"git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
"git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]]";
#define REF_UNKNOWN_TYPE 0x00
#define REF_LOCAL_BRANCH 0x01
@ -22,6 +22,8 @@ static const char builtin_branch_usage[] =
static const char *head;
static unsigned char head_sha1[20];
static int branch_track_remotes;
static int branch_use_color;
static char branch_colors[][COLOR_MAXLEN] = {
"\033[m", /* reset */
@ -59,11 +61,14 @@ int git_branch_config(const char *var, const char *value)
branch_use_color = git_config_colorbool(var, value);
return 0;
}
if (!strncmp(var, "color.branch.", 13)) {
if (!prefixcmp(var, "color.branch.")) {
int slot = parse_branch_color_slot(var, 13);
color_parse(value, var, branch_colors[slot]);
return 0;
}
if (!strcmp(var, "branch.autosetupmerge"))
branch_track_remotes = git_config_bool(var, value);
return git_default_config(var, value);
}
@ -134,7 +139,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
*/
if (!force &&
!in_merge_bases(rev, head_rev)) {
!in_merge_bases(rev, &head_rev, 1)) {
error("The branch '%s' is not a strict subset of "
"your current HEAD.\n"
"If you are sure you want to delete it, "
@ -178,13 +183,13 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
int len;
/* Detect kind */
if (!strncmp(refname, "refs/heads/", 11)) {
if (!prefixcmp(refname, "refs/heads/")) {
kind = REF_LOCAL_BRANCH;
refname += 11;
} else if (!strncmp(refname, "refs/remotes/", 13)) {
} else if (!prefixcmp(refname, "refs/remotes/")) {
kind = REF_REMOTE_BRANCH;
refname += 13;
} else if (!strncmp(refname, "refs/tags/", 10)) {
} else if (!prefixcmp(refname, "refs/tags/")) {
kind = REF_TAG;
refname += 10;
}
@ -289,12 +294,13 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
detached = (detached && (kinds & REF_LOCAL_BRANCH));
if (detached) {
struct ref_item item;
item.name = "(no branch)";
item.name = xstrdup("(no branch)");
item.kind = REF_LOCAL_BRANCH;
hashcpy(item.sha1, head_sha1);
if (strlen(item.name) > ref_list.maxwidth)
ref_list.maxwidth = strlen(item.name);
print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
free(item.name);
}
for (i = 0; i < ref_list.index; i++) {
@ -308,14 +314,119 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
free_ref_list(&ref_list);
}
static char *config_repo;
static char *config_remote;
static const char *start_ref;
static int start_len;
static int base_len;
static int get_remote_branch_name(const char *value)
{
const char *colon;
const char *end;
if (*value == '+')
value++;
colon = strchr(value, ':');
if (!colon)
return 0;
end = value + strlen(value);
/* Try an exact match first. */
if (!strcmp(colon + 1, start_ref)) {
/* Truncate the value before the colon. */
nfasprintf(&config_repo, "%.*s", colon - value, value);
return 1;
}
/* Try with a wildcard match now. */
if (end - value > 2 && end[-2] == '/' && end[-1] == '*' &&
colon - value > 2 && colon[-2] == '/' && colon[-1] == '*' &&
(end - 2) - (colon + 1) == base_len &&
!strncmp(colon + 1, start_ref, base_len)) {
/* Replace the star with the remote branch name. */
nfasprintf(&config_repo, "%.*s%s",
(colon - 2) - value, value,
start_ref + base_len);
return 1;
}
return 0;
}
static int get_remote_config(const char *key, const char *value)
{
const char *var;
if (prefixcmp(key, "remote."))
return 0;
var = strrchr(key, '.');
if (var == key + 6)
return 0;
if (!strcmp(var, ".fetch") && get_remote_branch_name(value))
nfasprintf(&config_remote, "%.*s", var - (key + 7), key + 7);
return 0;
}
static void set_branch_merge(const char *name, const char *config_remote,
const char *config_repo)
{
char key[1024];
if (sizeof(key) <=
snprintf(key, sizeof(key), "branch.%s.remote", name))
die("what a long branch name you have!");
git_config_set(key, config_remote);
/*
* We do not have to check if we have enough space for
* the 'merge' key, since it's shorter than the
* previous 'remote' key, which we already checked.
*/
snprintf(key, sizeof(key), "branch.%s.merge", name);
git_config_set(key, config_repo);
}
static void set_branch_defaults(const char *name, const char *real_ref)
{
const char *slash = strrchr(real_ref, '/');
if (!slash)
return;
start_ref = real_ref;
start_len = strlen(real_ref);
base_len = slash - real_ref;
git_config(get_remote_config);
if (!config_repo && !config_remote &&
!prefixcmp(real_ref, "refs/heads/")) {
set_branch_merge(name, ".", real_ref);
printf("Branch %s set up to track local branch %s.\n",
name, real_ref);
}
if (config_repo && config_remote) {
set_branch_merge(name, config_remote, config_repo);
printf("Branch %s set up to track remote branch %s.\n",
name, real_ref);
}
if (config_repo)
free(config_repo);
if (config_remote)
free(config_remote);
}
static void create_branch(const char *name, const char *start_name,
unsigned char *start_sha1,
int force, int reflog)
int force, int reflog, int track)
{
struct ref_lock *lock;
struct commit *commit;
unsigned char sha1[20];
char ref[PATH_MAX], msg[PATH_MAX + 20];
char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
int forcing = 0;
snprintf(ref, sizeof ref, "refs/heads/%s", name);
@ -330,12 +441,23 @@ static void create_branch(const char *name, const char *start_name,
forcing = 1;
}
if (start_sha1)
/* detached HEAD */
hashcpy(sha1, start_sha1);
else if (get_sha1(start_name, sha1))
real_ref = NULL;
if (get_sha1(start_name, sha1))
die("Not a valid object name: '%s'.", start_name);
switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
case 0:
/* Not branching from any existing branch */
real_ref = NULL;
break;
case 1:
/* Unique completion -- good */
break;
default:
die("Ambiguous object name: '%s'.", start_name);
break;
}
if ((commit = lookup_commit_reference(sha1)) == NULL)
die("Not a valid branch point: '%s'.", start_name);
hashcpy(sha1, commit->object.sha1);
@ -354,8 +476,17 @@ static void create_branch(const char *name, const char *start_name,
snprintf(msg, sizeof msg, "branch: Created from %s",
start_name);
/* When branching off a remote branch, set up so that git-pull
automatically merges from there. So far, this is only done for
remotes registered via .git/config. */
if (real_ref && track)
set_branch_defaults(name, real_ref);
if (write_ref_sha1(lock, sha1, msg) < 0)
die("Failed to write ref: %s.", strerror(errno));
if (real_ref)
free(real_ref);
}
static void rename_branch(const char *oldname, const char *newname, int force)
@ -397,11 +528,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
int delete = 0, force_delete = 0, force_create = 0;
int rename = 0, force_rename = 0;
int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
int reflog = 0;
int reflog = 0, track;
int kinds = REF_LOCAL_BRANCH;
int i;
git_config(git_branch_config);
track = branch_track_remotes;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@ -412,6 +544,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
i++;
break;
}
if (!strcmp(arg, "--track")) {
track = 1;
continue;
}
if (!strcmp(arg, "--no-track")) {
track = 0;
continue;
}
if (!strcmp(arg, "-d")) {
delete = 1;
continue;
@ -446,8 +586,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
reflog = 1;
continue;
}
if (!strncmp(arg, "--abbrev=", 9)) {
abbrev = atoi(arg+9);
if (!prefixcmp(arg, "--no-abbrev")) {
abbrev = 0;
continue;
}
if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg + 9, NULL, 10);
if (abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
else if (abbrev > 40)
abbrev = 40;
continue;
}
if (!strcmp(arg, "-v")) {
@ -476,7 +624,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
detached = 1;
}
else {
if (strncmp(head, "refs/heads/", 11))
if (prefixcmp(head, "refs/heads/"))
die("HEAD not found below refs/heads!");
head += 11;
}
@ -489,10 +637,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
rename_branch(head, argv[i], force_rename);
else if (rename && (i == argc - 2))
rename_branch(argv[i], argv[i + 1], force_rename);
else if (i == argc - 1)
create_branch(argv[i], head, head_sha1, force_create, reflog);
else if (i == argc - 2)
create_branch(argv[i], argv[i+1], NULL, force_create, reflog);
else if (i == argc - 1 || i == argc - 2)
create_branch(argv[i], (i == argc - 2) ? argv[i+1] : head,
force_create, reflog, track);
else
usage(builtin_branch_usage);

380
builtin-bundle.c Normal file
View File

@ -0,0 +1,380 @@
#include "cache.h"
#include "object.h"
#include "commit.h"
#include "diff.h"
#include "revision.h"
#include "list-objects.h"
#include "run-command.h"
/*
* Basic handler for bundle files to connect repositories via sneakernet.
* Invocation must include action.
* This function can create a bundle or provide information on an existing
* bundle supporting git-fetch, git-pull, and git-ls-remote
*/
static const char *bundle_usage="git-bundle (create <bundle> <git-rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
static const char bundle_signature[] = "# v2 git bundle\n";
struct ref_list {
unsigned int nr, alloc;
struct ref_list_entry {
unsigned char sha1[20];
char *name;
} *list;
};
static void add_to_ref_list(const unsigned char *sha1, const char *name,
struct ref_list *list)
{
if (list->nr + 1 >= list->alloc) {
list->alloc = alloc_nr(list->nr + 1);
list->list = xrealloc(list->list,
list->alloc * sizeof(list->list[0]));
}
memcpy(list->list[list->nr].sha1, sha1, 20);
list->list[list->nr].name = xstrdup(name);
list->nr++;
}
struct bundle_header {
struct ref_list prerequisites;
struct ref_list references;
};
/* this function returns the length of the string */
static int read_string(int fd, char *buffer, int size)
{
int i;
for (i = 0; i < size - 1; i++) {
int count = xread(fd, buffer + i, 1);
if (count < 0)
return error("Read error: %s", strerror(errno));
if (count == 0) {
i--;
break;
}
if (buffer[i] == '\n')
break;
}
buffer[i + 1] = '\0';
return i + 1;
}
/* returns an fd */
static int read_header(const char *path, struct bundle_header *header) {
char buffer[1024];
int fd = open(path, O_RDONLY);
if (fd < 0)
return error("could not open '%s'", path);
if (read_string(fd, buffer, sizeof(buffer)) < 0 ||
strcmp(buffer, bundle_signature)) {
close(fd);
return error("'%s' does not look like a v2 bundle file", path);
}
while (read_string(fd, buffer, sizeof(buffer)) > 0
&& buffer[0] != '\n') {
int is_prereq = buffer[0] == '-';
int offset = is_prereq ? 1 : 0;
int len = strlen(buffer);
unsigned char sha1[20];
struct ref_list *list = is_prereq ? &header->prerequisites
: &header->references;
char delim;
if (buffer[len - 1] == '\n')
buffer[len - 1] = '\0';
if (get_sha1_hex(buffer + offset, sha1)) {
warn("unrecognized header: %s", buffer);
continue;
}
delim = buffer[40 + offset];
if (!isspace(delim) && (delim != '\0' || !is_prereq))
die ("invalid header: %s", buffer);
add_to_ref_list(sha1, isspace(delim) ?
buffer + 41 + offset : "", list);
}
return fd;
}
static int list_refs(struct ref_list *r, int argc, const char **argv)
{
int i;
for (i = 0; i < r->nr; i++) {
if (argc > 1) {
int j;
for (j = 1; j < argc; j++)
if (!strcmp(r->list[i].name, argv[j]))
break;
if (j == argc)
continue;
}
printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
r->list[i].name);
}
return 0;
}
#define PREREQ_MARK (1u<<16)
static int verify_bundle(struct bundle_header *header, int verbose)
{
/*
* Do fast check, then if any prereqs are missing then go line by line
* to be verbose about the errors
*/
struct ref_list *p = &header->prerequisites;
struct rev_info revs;
const char *argv[] = {NULL, "--all"};
struct object_array refs;
struct commit *commit;
int i, ret = 0, req_nr;
const char *message = "Repository lacks these prerequisite commits:";
init_revisions(&revs, NULL);
for (i = 0; i < p->nr; i++) {
struct ref_list_entry *e = p->list + i;
struct object *o = parse_object(e->sha1);
if (o) {
o->flags |= PREREQ_MARK;
add_pending_object(&revs, o, e->name);
continue;
}
if (++ret == 1)
error(message);
error("%s %s", sha1_to_hex(e->sha1), e->name);
}
if (revs.pending.nr != p->nr)
return ret;
req_nr = revs.pending.nr;
setup_revisions(2, argv, &revs, NULL);
memset(&refs, 0, sizeof(struct object_array));
for (i = 0; i < revs.pending.nr; i++) {
struct object_array_entry *e = revs.pending.objects + i;
add_object_array(e->item, e->name, &refs);
}
prepare_revision_walk(&revs);
i = req_nr;
while (i && (commit = get_revision(&revs)))
if (commit->object.flags & PREREQ_MARK)
i--;
for (i = 0; i < req_nr; i++)
if (!(refs.objects[i].item->flags & SHOWN)) {
if (++ret == 1)
error(message);
error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
refs.objects[i].name);
}
for (i = 0; i < refs.nr; i++)
clear_commit_marks((struct commit *)refs.objects[i].item, -1);
if (verbose) {
struct ref_list *r;
r = &header->references;
printf("The bundle contains %d ref%s\n",
r->nr, (1 < r->nr) ? "s" : "");
list_refs(r, 0, NULL);
r = &header->prerequisites;
printf("The bundle requires these %d ref%s\n",
r->nr, (1 < r->nr) ? "s" : "");
list_refs(r, 0, NULL);
}
return ret;
}
static int list_heads(struct bundle_header *header, int argc, const char **argv)
{
return list_refs(&header->references, argc, argv);
}
static int create_bundle(struct bundle_header *header, const char *path,
int argc, const char **argv)
{
int bundle_fd = -1;
const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
const char **argv_pack = xmalloc(5 * sizeof(const char *));
int i, ref_count = 0;
char buffer[1024];
struct rev_info revs;
struct child_process rls;
bundle_fd = (!strcmp(path, "-") ? 1 :
open(path, O_CREAT | O_EXCL | O_WRONLY, 0666));
if (bundle_fd < 0)
return error("Could not create '%s': %s", path, strerror(errno));
/* write signature */
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
/* init revs to list objects for pack-objects later */
save_commit_buffer = 0;
init_revisions(&revs, NULL);
/* write prerequisites */
memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *));
argv_boundary[0] = "rev-list";
argv_boundary[1] = "--boundary";
argv_boundary[2] = "--pretty=oneline";
argv_boundary[argc + 2] = NULL;
memset(&rls, 0, sizeof(rls));
rls.argv = argv_boundary;
rls.out = -1;
rls.git_cmd = 1;
if (start_command(&rls))
return -1;
while ((i = read_string(rls.out, buffer, sizeof(buffer))) > 0) {
unsigned char sha1[20];
if (buffer[0] == '-') {
write_or_die(bundle_fd, buffer, i);
if (!get_sha1_hex(buffer + 1, sha1)) {
struct object *object = parse_object(sha1);
object->flags |= UNINTERESTING;
add_pending_object(&revs, object, buffer);
}
} else if (!get_sha1_hex(buffer, sha1)) {
struct object *object = parse_object(sha1);
object->flags |= SHOWN;
}
}
if (finish_command(&rls))
return error("rev-list died");
/* write references */
argc = setup_revisions(argc, argv, &revs, NULL);
if (argc > 1)
return error("unrecognized argument: %s'", argv[1]);
for (i = 0; i < revs.pending.nr; i++) {
struct object_array_entry *e = revs.pending.objects + i;
unsigned char sha1[20];
char *ref;
if (e->item->flags & UNINTERESTING)
continue;
if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
continue;
/*
* Make sure the refs we wrote out is correct; --max-count and
* other limiting options could have prevented all the tips
* from getting output.
*/
if (!(e->item->flags & SHOWN)) {
warn("ref '%s' is excluded by the rev-list options",
e->name);
continue;
}
ref_count++;
write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
write_or_die(bundle_fd, " ", 1);
write_or_die(bundle_fd, ref, strlen(ref));
write_or_die(bundle_fd, "\n", 1);
free(ref);
}
if (!ref_count)
die ("Refusing to create empty bundle.");
/* end header */
write_or_die(bundle_fd, "\n", 1);
/* write pack */
argv_pack[0] = "pack-objects";
argv_pack[1] = "--all-progress";
argv_pack[2] = "--stdout";
argv_pack[3] = "--thin";
argv_pack[4] = NULL;
memset(&rls, 0, sizeof(rls));
rls.argv = argv_pack;
rls.in = -1;
rls.out = bundle_fd;
rls.git_cmd = 1;
if (start_command(&rls))
return error("Could not spawn pack-objects");
for (i = 0; i < revs.pending.nr; i++) {
struct object *object = revs.pending.objects[i].item;
if (object->flags & UNINTERESTING)
write(rls.in, "^", 1);
write(rls.in, sha1_to_hex(object->sha1), 40);
write(rls.in, "\n", 1);
}
if (finish_command(&rls))
return error ("pack-objects died");
return 0;
}
static int unbundle(struct bundle_header *header, int bundle_fd,
int argc, const char **argv)
{
const char *argv_index_pack[] = {"index-pack",
"--fix-thin", "--stdin", NULL};
struct child_process ip;
if (verify_bundle(header, 0))
return -1;
memset(&ip, 0, sizeof(ip));
ip.argv = argv_index_pack;
ip.in = bundle_fd;
ip.no_stdout = 1;
ip.git_cmd = 1;
if (run_command(&ip))
return error("index-pack died");
return list_heads(header, argc, argv);
}
int cmd_bundle(int argc, const char **argv, const char *prefix)
{
struct bundle_header header;
int nongit = 0;
const char *cmd, *bundle_file;
int bundle_fd = -1;
char buffer[PATH_MAX];
if (argc < 3)
usage(bundle_usage);
cmd = argv[1];
bundle_file = argv[2];
argc -= 2;
argv += 2;
prefix = setup_git_directory_gently(&nongit);
if (prefix && bundle_file[0] != '/') {
snprintf(buffer, sizeof(buffer), "%s/%s", prefix, bundle_file);
bundle_file = buffer;
}
memset(&header, 0, sizeof(header));
if (strcmp(cmd, "create") &&
(bundle_fd = read_header(bundle_file, &header)) < 0)
return 1;
if (!strcmp(cmd, "verify")) {
close(bundle_fd);
if (verify_bundle(&header, 1))
return 1;
fprintf(stderr, "%s is okay\n", bundle_file);
return 0;
}
if (!strcmp(cmd, "list-heads")) {
close(bundle_fd);
return !!list_heads(&header, argc, argv);
}
if (!strcmp(cmd, "create")) {
if (nongit)
die("Need a repository to create a bundle.");
return !!create_bundle(&header, bundle_file, argc, argv);
} else if (!strcmp(cmd, "unbundle")) {
if (nongit)
die("Need a repository to unbundle.");
return !!unbundle(&header, bundle_fd, argc, argv);
} else
usage(bundle_usage);
}

View File

@ -79,7 +79,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
int cmd_cat_file(int argc, const char **argv, const char *prefix)
{
unsigned char sha1[20];
char type[20];
enum object_type type;
void *buf;
unsigned long size;
int opt;
@ -100,14 +100,16 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
buf = NULL;
switch (opt) {
case 't':
if (!sha1_object_info(sha1, type, NULL)) {
printf("%s\n", type);
type = sha1_object_info(sha1, NULL);
if (type > 0) {
printf("%s\n", typename(type));
return 0;
}
break;
case 's':
if (!sha1_object_info(sha1, type, &size)) {
type = sha1_object_info(sha1, &size);
if (type > 0) {
printf("%lu\n", size);
return 0;
}
@ -117,17 +119,18 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
return !has_sha1_file(sha1);
case 'p':
if (sha1_object_info(sha1, type, NULL))
type = sha1_object_info(sha1, NULL);
if (type < 0)
die("Not a valid object name %s", argv[2]);
/* custom pretty-print here */
if (!strcmp(type, tree_type))
if (type == OBJ_TREE)
return cmd_ls_tree(2, argv + 1, NULL);
buf = read_sha1_file(sha1, type, &size);
buf = read_sha1_file(sha1, &type, &size);
if (!buf)
die("Cannot read object %s", argv[2]);
if (!strcmp(type, tag_type)) {
if (type == OBJ_TAG) {
pprint_tag(sha1, buf, size);
return 0;
}

View File

@ -223,12 +223,12 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
to_tempfile = 1;
continue;
}
if (!strncmp(arg, "--prefix=", 9)) {
if (!prefixcmp(arg, "--prefix=")) {
state.base_dir = arg+9;
state.base_dir_len = strlen(state.base_dir);
continue;
}
if (!strncmp(arg, "--stage=", 8)) {
if (!prefixcmp(arg, "--stage=")) {
if (!strcmp(arg + 8, "all")) {
to_tempfile = 1;
checkout_stage = CHECKOUT_ALL;

View File

@ -45,15 +45,14 @@ static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...)
memcpy(buf + size, one_line, len);
}
static void check_valid(unsigned char *sha1, const char *expect)
static void check_valid(unsigned char *sha1, enum object_type expect)
{
char type[20];
if (sha1_object_info(sha1, type, NULL))
enum object_type type = sha1_object_info(sha1, NULL);
if (type < 0)
die("%s is not a valid object", sha1_to_hex(sha1));
if (expect && strcmp(type, expect))
if (type != expect)
die("%s is not a valid '%s' object", sha1_to_hex(sha1),
expect);
typename(expect));
}
/*
@ -101,7 +100,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
if (get_sha1(argv[1], tree_sha1))
die("Not a valid object name %s", argv[1]);
check_valid(tree_sha1, tree_type);
check_valid(tree_sha1, OBJ_TREE);
for (i = 2; i < argc; i += 2) {
const char *a, *b;
a = argv[i]; b = argv[i+1];
@ -112,7 +111,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
die("Too many parents (%d max)", MAXPARENT);
if (get_sha1(b, parent_sha1[parents]))
die("Not a valid object name %s", b);
check_valid(parent_sha1[parents], commit_type);
check_valid(parent_sha1[parents], OBJ_COMMIT);
if (new_parent(parents))
parents++;
}

View File

@ -2,7 +2,7 @@
#include "cache.h"
static const char git_config_set_usage[] =
"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --list";
"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list";
static char *key;
static regex_t *key_regexp;
@ -64,7 +64,7 @@ static int get_value(const char* key_, const char* regex_)
int ret = -1;
char *tl;
char *global = NULL, *repo_config = NULL;
const char *local;
const char *system_wide = NULL, *local;
local = getenv(CONFIG_ENVIRONMENT);
if (!local) {
@ -74,6 +74,7 @@ static int get_value(const char* key_, const char* regex_)
local = repo_config = xstrdup(git_path("config"));
if (home)
global = xstrdup(mkpath("%s/.gitconfig", home));
system_wide = ETC_GITCONFIG;
}
key = xstrdup(key_);
@ -103,11 +104,15 @@ static int get_value(const char* key_, const char* regex_)
}
}
if (do_all && system_wide)
git_config_from_file(show_config, system_wide);
if (do_all && global)
git_config_from_file(show_config, global);
git_config_from_file(show_config, local);
if (!do_all && !seen && global)
git_config_from_file(show_config, global);
if (!do_all && !seen && system_wide)
git_config_from_file(show_config, system_wide);
free(key);
if (regexp) {
@ -147,7 +152,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)
} else {
die("$HOME not set");
}
} else if (!strcmp(argv[1], "--rename-section")) {
}
else if (!strcmp(argv[1], "--system"))
setenv("GIT_CONFIG", ETC_GITCONFIG, 1);
else if (!strcmp(argv[1], "--rename-section")) {
int ret;
if (argc != 4)
usage(git_config_set_usage);
@ -159,7 +167,21 @@ int cmd_config(int argc, const char **argv, const char *prefix)
return 1;
}
return 0;
} else
}
else if (!strcmp(argv[1], "--remove-section")) {
int ret;
if (argc != 3)
usage(git_config_set_usage);
ret = git_config_rename_section(argv[2], NULL);
if (ret < 0)
return ret;
if (ret == 0) {
fprintf(stderr, "No such section!\n");
return 1;
}
return 0;
}
else
break;
argc--;
argv++;

View File

@ -44,7 +44,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
if (lstat(path, &st) || !S_ISREG(st.st_mode))
bad = 1;
else
(*loose_size) += st.st_blocks;
(*loose_size) += xsize_t(st.st_blocks);
}
if (bad) {
if (verbose) {

View File

@ -52,7 +52,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
* If --tags, then any tags are used.
* Otherwise only annotated tags are used.
*/
if (!strncmp(path, "refs/tags/", 10)) {
if (!prefixcmp(path, "refs/tags/")) {
if (object->type == OBJ_TAG)
prio = 2;
else
@ -254,12 +254,12 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
all = 1;
else if (!strcmp(arg, "--tags"))
tags = 1;
else if (!strncmp(arg, "--abbrev=", 9)) {
else if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg + 9, NULL, 10);
if (abbrev != 0 && (abbrev < MINIMUM_ABBREV || 40 < abbrev))
abbrev = DEFAULT_ABBREV;
}
else if (!strncmp(arg, "--candidates=", 13)) {
else if (!prefixcmp(arg, "--candidates=")) {
max_candidates = strtoul(arg + 13, NULL, 10);
if (max_candidates < 1)
max_candidates = 1;

View File

@ -10,42 +10,26 @@
#include "builtin.h"
static const char diff_files_usage[] =
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc|-n|--no-index] [<common diff options>] [<path>...]"
COMMON_DIFF_OPTIONS_HELP;
int cmd_diff_files(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;
int silent = 0;
int nongit = 0;
int result;
prefix = setup_git_directory_gently(&nongit);
init_revisions(&rev, prefix);
git_config(git_default_config); /* no "diff" UI options */
rev.abbrev = 0;
argc = setup_revisions(argc, argv, &rev, NULL);
while (1 < argc && argv[1][0] == '-') {
if (!strcmp(argv[1], "--base"))
rev.max_count = 1;
else if (!strcmp(argv[1], "--ours"))
rev.max_count = 2;
else if (!strcmp(argv[1], "--theirs"))
rev.max_count = 3;
else if (!strcmp(argv[1], "-q"))
silent = 1;
else
usage(diff_files_usage);
argv++; argc--;
}
if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))
argc = 0;
else
argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
/*
* Make sure there are NO revision (i.e. pending object) parameter,
* rev.max_count is reasonable (0 <= n <= 3),
* there is no other revision filtering parameters.
*/
if (rev.pending.nr ||
rev.min_age != -1 || rev.max_age != -1)
usage(diff_files_usage);
return run_diff_files(&rev, silent);
result = run_diff_files_cmd(&rev, argc, argv);
return rev.diffopt.exit_with_status ? rev.diffopt.has_changes: result;
}

View File

@ -14,6 +14,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
struct rev_info rev;
int cached = 0;
int i;
int result;
init_revisions(&rev, prefix);
git_config(git_default_config); /* no "diff" UI options */
@ -38,5 +39,10 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
if (rev.pending.nr != 1 ||
rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
usage(diff_cache_usage);
return run_diff_index(&rev, cached);
if (read_cache() < 0) {
perror("read_cache");
return -1;
}
result = run_diff_index(&rev, cached);
return rev.diffopt.exit_with_status ? rev.diffopt.has_changes: result;
}

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 2005 Junio C Hamano
*/
#include "cache.h"
#include "diff.h"
#include "builtin.h"
static struct diff_options diff_options;
static const char diff_stages_usage[] =
"git-diff-stages [<common diff options>] <stage1> <stage2> [<path>...]"
COMMON_DIFF_OPTIONS_HELP;
static void diff_stages(int stage1, int stage2, const char **pathspec)
{
int i = 0;
while (i < active_nr) {
struct cache_entry *ce, *stages[4] = { NULL, };
struct cache_entry *one, *two;
const char *name;
int len, skip;
ce = active_cache[i];
skip = !ce_path_match(ce, pathspec);
len = ce_namelen(ce);
name = ce->name;
for (;;) {
int stage = ce_stage(ce);
stages[stage] = ce;
if (active_nr <= ++i)
break;
ce = active_cache[i];
if (ce_namelen(ce) != len ||
memcmp(name, ce->name, len))
break;
}
one = stages[stage1];
two = stages[stage2];
if (skip || (!one && !two))
continue;
if (!one)
diff_addremove(&diff_options, '+', ntohl(two->ce_mode),
two->sha1, name, NULL);
else if (!two)
diff_addremove(&diff_options, '-', ntohl(one->ce_mode),
one->sha1, name, NULL);
else if (hashcmp(one->sha1, two->sha1) ||
(one->ce_mode != two->ce_mode) ||
diff_options.find_copies_harder)
diff_change(&diff_options,
ntohl(one->ce_mode), ntohl(two->ce_mode),
one->sha1, two->sha1, name, NULL);
}
}
int cmd_diff_stages(int ac, const char **av, const char *prefix)
{
int stage1, stage2;
const char **pathspec = NULL;
git_config(git_default_config); /* no "diff" UI options */
read_cache();
diff_setup(&diff_options);
while (1 < ac && av[1][0] == '-') {
const char *arg = av[1];
if (!strcmp(arg, "-r"))
; /* as usual */
else {
int diff_opt_cnt;
diff_opt_cnt = diff_opt_parse(&diff_options,
av+1, ac-1);
if (diff_opt_cnt < 0)
usage(diff_stages_usage);
else if (diff_opt_cnt) {
av += diff_opt_cnt;
ac -= diff_opt_cnt;
continue;
}
else
usage(diff_stages_usage);
}
ac--; av++;
}
if (!diff_options.output_format)
diff_options.output_format = DIFF_FORMAT_RAW;
if (ac < 3 ||
sscanf(av[1], "%d", &stage1) != 1 ||
! (0 <= stage1 && stage1 <= 3) ||
sscanf(av[2], "%d", &stage2) != 1 ||
! (0 <= stage2 && stage2 <= 3))
usage(diff_stages_usage);
av += 3; /* The rest from av[0] are for paths restriction. */
pathspec = get_pathspec(prefix, av);
if (diff_setup_done(&diff_options) < 0)
usage(diff_stages_usage);
diff_stages(stage1, stage2, pathspec);
diffcore_std(&diff_options);
diff_flush(&diff_options);
return 0;
}

View File

@ -118,7 +118,8 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
}
if (!read_stdin)
return 0;
return opt->diffopt.exit_with_status ?
opt->diffopt.has_changes: 0;
if (opt->diffopt.detect_rename)
opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE |
@ -133,5 +134,5 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
else
diff_tree_stdin(line);
}
return 0;
return opt->diffopt.exit_with_status ? opt->diffopt.has_changes: 0;
}

View File

@ -25,40 +25,6 @@ struct blobinfo {
static const char builtin_diff_usage[] =
"git-diff <options> <rev>{0,2} -- <path>*";
static int builtin_diff_files(struct rev_info *revs,
int argc, const char **argv)
{
int silent = 0;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--base"))
revs->max_count = 1;
else if (!strcmp(arg, "--ours"))
revs->max_count = 2;
else if (!strcmp(arg, "--theirs"))
revs->max_count = 3;
else if (!strcmp(arg, "-q"))
silent = 1;
else
usage(builtin_diff_usage);
argv++; argc--;
}
/*
* Make sure there are NO revision (i.e. pending object) parameter,
* specified rev.max_count is reasonable (0 <= n <= 3), and
* there is no other revision filtering parameter.
*/
if (revs->pending.nr ||
revs->min_age != -1 ||
revs->max_age != -1 ||
3 < revs->max_count)
usage(builtin_diff_usage);
if (revs->max_count < 0 &&
(revs->diffopt.output_format & DIFF_FORMAT_PATCH))
revs->combine_merges = revs->dense_combined_merges = 1;
return run_diff_files(revs, silent);
}
static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
@ -151,6 +117,10 @@ static int builtin_diff_index(struct rev_info *revs,
revs->max_count != -1 || revs->min_age != -1 ||
revs->max_age != -1)
usage(builtin_diff_usage);
if (read_cache() < 0) {
perror("read_cache");
return -1;
}
return run_diff_index(revs, cached);
}
@ -219,6 +189,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
int ents = 0, blobs = 0, paths = 0;
const char *path = NULL;
struct blobinfo blob[2];
int nongit = 0;
int result = 0;
/*
* We could get N tree-ish in the rev.pending_objects list.
@ -240,10 +212,14 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
* Other cases are errors.
*/
prefix = setup_git_directory_gently(&nongit);
git_config(git_diff_ui_config);
init_revisions(&rev, prefix);
argc = setup_revisions(argc, argv, &rev, NULL);
if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))
argc = 0;
else
argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format) {
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
if (diff_setup_done(&rev.diffopt) < 0)
@ -261,6 +237,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
break;
else if (!strcmp(arg, "--cached")) {
add_head(&rev);
if (!rev.pending.nr)
die("No HEAD commit to compare with (yet)");
break;
}
}
@ -315,17 +293,17 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
if (!ents) {
switch (blobs) {
case 0:
return builtin_diff_files(&rev, argc, argv);
result = run_diff_files_cmd(&rev, argc, argv);
break;
case 1:
if (paths != 1)
usage(builtin_diff_usage);
return builtin_diff_b_f(&rev, argc, argv, blob, path);
result = builtin_diff_b_f(&rev, argc, argv, blob, path);
break;
case 2:
if (paths)
usage(builtin_diff_usage);
return builtin_diff_blobs(&rev, argc, argv, blob);
result = builtin_diff_blobs(&rev, argc, argv, blob);
break;
default:
usage(builtin_diff_usage);
@ -334,19 +312,21 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
else if (blobs)
usage(builtin_diff_usage);
else if (ents == 1)
return builtin_diff_index(&rev, argc, argv);
result = builtin_diff_index(&rev, argc, argv);
else if (ents == 2)
return builtin_diff_tree(&rev, argc, argv, ent);
result = builtin_diff_tree(&rev, argc, argv, ent);
else if ((ents == 3) && (ent[0].item->flags & UNINTERESTING)) {
/* diff A...B where there is one sane merge base between
* A and B. We have ent[0] == merge-base, ent[1] == A,
* and ent[2] == B. Show diff between the base and B.
*/
ent[1] = ent[2];
return builtin_diff_tree(&rev, argc, argv, ent);
result = builtin_diff_tree(&rev, argc, argv, ent);
}
else
return builtin_diff_combined(&rev, argc, argv,
result = builtin_diff_combined(&rev, argc, argv,
ent, ents);
usage(builtin_diff_usage);
if (rev.diffopt.exit_with_status)
result = rev.diffopt.has_changes;
return result;
}

505
builtin-fetch--tool.c Normal file
View File

@ -0,0 +1,505 @@
#include "cache.h"
#include "refs.h"
#include "commit.h"
#define CHUNK_SIZE 1024
static char *get_stdin(void)
{
int offset = 0;
char *data = xmalloc(CHUNK_SIZE);
while (1) {
int cnt = xread(0, data + offset, CHUNK_SIZE);
if (cnt < 0)
die("error reading standard input: %s",
strerror(errno));
if (cnt == 0) {
data[offset] = 0;
break;
}
offset += cnt;
data = xrealloc(data, offset + CHUNK_SIZE);
}
return data;
}
static void show_new(enum object_type type, unsigned char *sha1_new)
{
fprintf(stderr, " %s: %s\n", typename(type),
find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
}
static int update_ref(const char *action,
const char *refname,
unsigned char *sha1,
unsigned char *oldval)
{
int len;
char msg[1024];
char *rla = getenv("GIT_REFLOG_ACTION");
static struct ref_lock *lock;
if (!rla)
rla = "(reflog update)";
len = snprintf(msg, sizeof(msg), "%s: %s", rla, action);
if (sizeof(msg) <= len)
die("insanely long action");
lock = lock_any_ref_for_update(refname, oldval);
if (!lock)
return 1;
if (write_ref_sha1(lock, sha1, msg) < 0)
return 1;
return 0;
}
static int update_local_ref(const char *name,
const char *new_head,
const char *note,
int verbose, int force)
{
unsigned char sha1_old[20], sha1_new[20];
char oldh[41], newh[41];
struct commit *current, *updated;
enum object_type type;
if (get_sha1_hex(new_head, sha1_new))
die("malformed object name %s", new_head);
type = sha1_object_info(sha1_new, NULL);
if (type < 0)
die("object %s not found", new_head);
if (!*name) {
/* Not storing */
if (verbose) {
fprintf(stderr, "* fetched %s\n", note);
show_new(type, sha1_new);
}
return 0;
}
if (get_sha1(name, sha1_old)) {
char *msg;
just_store:
/* new ref */
if (!strncmp(name, "refs/tags/", 10))
msg = "storing tag";
else
msg = "storing head";
fprintf(stderr, "* %s: storing %s\n",
name, note);
show_new(type, sha1_new);
return update_ref(msg, name, sha1_new, NULL);
}
if (!hashcmp(sha1_old, sha1_new)) {
if (verbose) {
fprintf(stderr, "* %s: same as %s\n", name, note);
show_new(type, sha1_new);
}
return 0;
}
if (!strncmp(name, "refs/tags/", 10)) {
fprintf(stderr, "* %s: updating with %s\n", name, note);
show_new(type, sha1_new);
return update_ref("updating tag", name, sha1_new, NULL);
}
current = lookup_commit_reference(sha1_old);
updated = lookup_commit_reference(sha1_new);
if (!current || !updated)
goto just_store;
strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcpy(newh, find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
if (in_merge_bases(current, &updated, 1)) {
fprintf(stderr, "* %s: fast forward to %s\n",
name, note);
fprintf(stderr, " old..new: %s..%s\n", oldh, newh);
return update_ref("fast forward", name, sha1_new, sha1_old);
}
if (!force) {
fprintf(stderr,
"* %s: not updating to non-fast forward %s\n",
name, note);
fprintf(stderr,
" old...new: %s...%s\n", oldh, newh);
return 1;
}
fprintf(stderr,
"* %s: forcing update to non-fast forward %s\n",
name, note);
fprintf(stderr, " old...new: %s...%s\n", oldh, newh);
return update_ref("forced-update", name, sha1_new, sha1_old);
}
static int append_fetch_head(FILE *fp,
const char *head, const char *remote,
const char *remote_name, const char *remote_nick,
const char *local_name, int not_for_merge,
int verbose, int force)
{
struct commit *commit;
int remote_len, i, note_len;
unsigned char sha1[20];
char note[1024];
const char *what, *kind;
if (get_sha1(head, sha1))
return error("Not a valid object name: %s", head);
commit = lookup_commit_reference(sha1);
if (!commit)
not_for_merge = 1;
if (!strcmp(remote_name, "HEAD")) {
kind = "";
what = "";
}
else if (!strncmp(remote_name, "refs/heads/", 11)) {
kind = "branch";
what = remote_name + 11;
}
else if (!strncmp(remote_name, "refs/tags/", 10)) {
kind = "tag";
what = remote_name + 10;
}
else if (!strncmp(remote_name, "refs/remotes/", 13)) {
kind = "remote branch";
what = remote_name + 13;
}
else {
kind = "";
what = remote_name;
}
remote_len = strlen(remote);
for (i = remote_len - 1; remote[i] == '/' && 0 <= i; i--)
;
remote_len = i + 1;
if (4 < i && !strncmp(".git", remote + i - 3, 4))
remote_len = i - 3;
note_len = 0;
if (*what) {
if (*kind)
note_len += sprintf(note + note_len, "%s ", kind);
note_len += sprintf(note + note_len, "'%s' of ", what);
}
note_len += sprintf(note + note_len, "%.*s", remote_len, remote);
fprintf(fp, "%s\t%s\t%s\n",
sha1_to_hex(commit ? commit->object.sha1 : sha1),
not_for_merge ? "not-for-merge" : "",
note);
return update_local_ref(local_name, head, note, verbose, force);
}
static char *keep;
static void remove_keep(void)
{
if (keep && *keep)
unlink(keep);
}
static void remove_keep_on_signal(int signo)
{
remove_keep();
signal(SIGINT, SIG_DFL);
raise(signo);
}
static char *find_local_name(const char *remote_name, const char *refs,
int *force_p, int *not_for_merge_p)
{
const char *ref = refs;
int len = strlen(remote_name);
while (ref) {
const char *next;
int single_force, not_for_merge;
while (*ref == '\n')
ref++;
if (!*ref)
break;
next = strchr(ref, '\n');
single_force = not_for_merge = 0;
if (*ref == '+') {
single_force = 1;
ref++;
}
if (*ref == '.') {
not_for_merge = 1;
ref++;
if (*ref == '+') {
single_force = 1;
ref++;
}
}
if (!strncmp(remote_name, ref, len) && ref[len] == ':') {
const char *local_part = ref + len + 1;
char *ret;
int retlen;
if (!next)
retlen = strlen(local_part);
else
retlen = next - local_part;
ret = xmalloc(retlen + 1);
memcpy(ret, local_part, retlen);
ret[retlen] = 0;
*force_p = single_force;
*not_for_merge_p = not_for_merge;
return ret;
}
ref = next;
}
return NULL;
}
static int fetch_native_store(FILE *fp,
const char *remote,
const char *remote_nick,
const char *refs,
int verbose, int force)
{
char buffer[1024];
int err = 0;
signal(SIGINT, remove_keep_on_signal);
atexit(remove_keep);
while (fgets(buffer, sizeof(buffer), stdin)) {
int len;
char *cp;
char *local_name;
int single_force, not_for_merge;
for (cp = buffer; *cp && !isspace(*cp); cp++)
;
if (*cp)
*cp++ = 0;
len = strlen(cp);
if (len && cp[len-1] == '\n')
cp[--len] = 0;
if (!strcmp(buffer, "failed"))
die("Fetch failure: %s", remote);
if (!strcmp(buffer, "pack"))
continue;
if (!strcmp(buffer, "keep")) {
char *od = get_object_directory();
int len = strlen(od) + strlen(cp) + 50;
keep = xmalloc(len);
sprintf(keep, "%s/pack/pack-%s.keep", od, cp);
continue;
}
local_name = find_local_name(cp, refs,
&single_force, &not_for_merge);
if (!local_name)
continue;
err |= append_fetch_head(fp,
buffer, remote, cp, remote_nick,
local_name, not_for_merge,
verbose, force || single_force);
}
return err;
}
static int parse_reflist(const char *reflist)
{
const char *ref;
printf("refs='");
for (ref = reflist; ref; ) {
const char *next;
while (*ref && isspace(*ref))
ref++;
if (!*ref)
break;
for (next = ref; *next && !isspace(*next); next++)
;
printf("\n%.*s", (int)(next - ref), ref);
ref = next;
}
printf("'\n");
printf("rref='");
for (ref = reflist; ref; ) {
const char *next, *colon;
while (*ref && isspace(*ref))
ref++;
if (!*ref)
break;
for (next = ref; *next && !isspace(*next); next++)
;
if (*ref == '.')
ref++;
if (*ref == '+')
ref++;
colon = strchr(ref, ':');
putchar('\n');
printf("%.*s", (int)((colon ? colon : next) - ref), ref);
ref = next;
}
printf("'\n");
return 0;
}
static int expand_refs_wildcard(const char *ls_remote_result, int numrefs,
const char **refs)
{
int i, matchlen, replacelen;
int found_one = 0;
const char *remote = *refs++;
numrefs--;
if (numrefs == 0) {
fprintf(stderr, "Nothing specified for fetching with remote.%s.fetch\n",
remote);
printf("empty\n");
}
for (i = 0; i < numrefs; i++) {
const char *ref = refs[i];
const char *lref = ref;
const char *colon;
const char *tail;
const char *ls;
const char *next;
if (*lref == '+')
lref++;
colon = strchr(lref, ':');
tail = lref + strlen(lref);
if (!(colon &&
2 < colon - lref &&
colon[-1] == '*' &&
colon[-2] == '/' &&
2 < tail - (colon + 1) &&
tail[-1] == '*' &&
tail[-2] == '/')) {
/* not a glob */
if (!found_one++)
printf("explicit\n");
printf("%s\n", ref);
continue;
}
/* glob */
if (!found_one++)
printf("glob\n");
/* lref to colon-2 is remote hierarchy name;
* colon+1 to tail-2 is local.
*/
matchlen = (colon-1) - lref;
replacelen = (tail-1) - (colon+1);
for (ls = ls_remote_result; ls; ls = next) {
const char *eol;
unsigned char sha1[20];
int namelen;
while (*ls && isspace(*ls))
ls++;
next = strchr(ls, '\n');
eol = !next ? (ls + strlen(ls)) : next;
if (!memcmp("^{}", eol-3, 3))
continue;
if (eol - ls < 40)
continue;
if (get_sha1_hex(ls, sha1))
continue;
ls += 40;
while (ls < eol && isspace(*ls))
ls++;
/* ls to next (or eol) is the name.
* is it identical to lref to colon-2?
*/
if ((eol - ls) <= matchlen ||
strncmp(ls, lref, matchlen))
continue;
/* Yes, it is a match */
namelen = eol - ls;
if (lref != ref)
putchar('+');
printf("%.*s:%.*s%.*s\n",
namelen, ls,
replacelen, colon + 1,
namelen - matchlen, ls + matchlen);
}
}
return 0;
}
int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
{
int verbose = 0;
int force = 0;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp("-v", arg))
verbose = 1;
else if (!strcmp("-f", arg))
force = 1;
else
break;
argc--;
argv++;
}
if (argc <= 1)
return error("Missing subcommand");
if (!strcmp("append-fetch-head", argv[1])) {
int result;
FILE *fp;
if (argc != 8)
return error("append-fetch-head takes 6 args");
fp = fopen(git_path("FETCH_HEAD"), "a");
result = append_fetch_head(fp, argv[2], argv[3],
argv[4], argv[5],
argv[6], !!argv[7][0],
verbose, force);
fclose(fp);
return result;
}
if (!strcmp("native-store", argv[1])) {
int result;
FILE *fp;
if (argc != 5)
return error("fetch-native-store takes 3 args");
fp = fopen(git_path("FETCH_HEAD"), "a");
result = fetch_native_store(fp, argv[2], argv[3], argv[4],
verbose, force);
fclose(fp);
return result;
}
if (!strcmp("parse-reflist", argv[1])) {
const char *reflist;
if (argc != 3)
return error("parse-reflist takes 1 arg");
reflist = argv[2];
if (!strcmp(reflist, "-"))
reflist = get_stdin();
return parse_reflist(reflist);
}
if (!strcmp("expand-refs-wildcard", argv[1])) {
const char *reflist;
if (argc < 4)
return error("expand-refs-wildcard takes at least 2 args");
reflist = argv[2];
if (!strcmp(reflist, "-"))
reflist = get_stdin();
return expand_refs_wildcard(reflist, argc - 3, argv + 3);
}
return error("Unknown subcommand: %s", argv[1]);
}

View File

@ -81,7 +81,7 @@ static int handle_line(char *line)
if (len < 43 || line[40] != '\t')
return 1;
if (!strncmp(line + 41, "not-for-merge", 13))
if (!prefixcmp(line + 41, "not-for-merge"))
return 0;
if (line[41] != '\t')
@ -119,15 +119,15 @@ static int handle_line(char *line)
if (pulling_head) {
origin = xstrdup(src);
src_data->head_status |= 1;
} else if (!strncmp(line, "branch ", 7)) {
} else if (!prefixcmp(line, "branch ")) {
origin = xstrdup(line + 7);
append_to_list(&src_data->branch, origin, NULL);
src_data->head_status |= 2;
} else if (!strncmp(line, "tag ", 4)) {
} else if (!prefixcmp(line, "tag ")) {
origin = line;
append_to_list(&src_data->tag, xstrdup(origin + 4), NULL);
src_data->head_status |= 2;
} else if (!strncmp(line, "remote branch ", 14)) {
} else if (!prefixcmp(line, "remote branch ")) {
origin = xstrdup(line + 14);
append_to_list(&src_data->r_branch, origin, NULL);
src_data->head_status |= 2;
@ -282,7 +282,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
if (!current_branch)
die("No current branch");
if (!strncmp(current_branch, "refs/heads/", 11))
if (!prefixcmp(current_branch, "refs/heads/"))
current_branch += 11;
while (fgets(line, sizeof(line), in)) {

View File

@ -173,8 +173,8 @@ static void verify_format(const char *format)
*/
static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
{
char type[20];
void *buf = read_sha1_file(sha1, type, sz);
enum object_type type;
void *buf = read_sha1_file(sha1, &type, sz);
if (buf)
*obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
@ -196,7 +196,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct object
if (deref)
name++;
if (!strcmp(name, "objecttype"))
v->s = type_names[obj->type];
v->s = typename(obj->type);
else if (!strcmp(name, "objectsize")) {
char *s = xmalloc(40);
sprintf(s, "%lu", sz);
@ -301,7 +301,7 @@ static const char *find_wholine(const char *who, int wholen, const char *buf, un
return "";
}
static char *copy_line(const char *buf)
static const char *copy_line(const char *buf)
{
const char *eol = strchr(buf, '\n');
char *line;
@ -315,7 +315,7 @@ static char *copy_line(const char *buf)
return line;
}
static char *copy_name(const char *buf)
static const char *copy_name(const char *buf)
{
const char *eol = strchr(buf, '\n');
const char *eoname = strstr(buf, " <");
@ -330,7 +330,7 @@ static char *copy_name(const char *buf)
return line;
}
static char *copy_email(const char *buf)
static const char *copy_email(const char *buf)
{
const char *email = strchr(buf, '<');
const char *eoemail = strchr(email, '>');
@ -814,7 +814,7 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix)
i++;
break;
}
if (!strncmp(arg, "--format=", 9)) {
if (!prefixcmp(arg, "--format=")) {
if (format)
die("more than one --format?");
format = arg + 9;
@ -844,7 +844,7 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix)
quote_style = QUOTE_TCL;
continue;
}
if (!strncmp(arg, "--count=", 8)) {
if (!prefixcmp(arg, "--count=")) {
if (maxcount)
die("more than one --count?");
maxcount = atoi(arg + 8);
@ -852,7 +852,7 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix)
die("The number %s did not parse", arg);
continue;
}
if (!strncmp(arg, "--sort=", 7)) {
if (!prefixcmp(arg, "--sort=")) {
struct ref_sort *s = xcalloc(1, sizeof(*s));
int len;

View File

@ -18,6 +18,9 @@ static int check_full;
static int check_strict;
static int keep_cache_objects;
static unsigned char head_sha1[20];
static int errors_found;
#define ERROR_OBJECT 01
#define ERROR_REACHABLE 02
#ifdef NO_D_INO_IN_DIRENT
#define SORT_DIRENT 0
@ -40,6 +43,7 @@ static int objerror(struct object *obj, const char *err, ...)
{
va_list params;
va_start(params, err);
errors_found |= ERROR_OBJECT;
objreport(obj, "error", err, params);
va_end(params);
return -1;
@ -67,9 +71,10 @@ static void check_reachable_object(struct object *obj)
* do a full fsck
*/
if (!obj->parsed) {
if (has_sha1_file(obj->sha1))
if (has_sha1_pack(obj->sha1, NULL))
return; /* it is in pack - forget about it */
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
errors_found |= ERROR_REACHABLE;
return;
}
@ -88,6 +93,7 @@ static void check_reachable_object(struct object *obj)
typename(obj->type), sha1_to_hex(obj->sha1));
printf(" to %7s %s\n",
typename(ref->type), sha1_to_hex(ref->sha1));
errors_found |= ERROR_REACHABLE;
}
}
}
@ -221,8 +227,7 @@ static int fsck_tree(struct tree *item)
const char *o_name;
const unsigned char *o_sha1;
desc.buf = item->buffer;
desc.size = item->size;
init_tree_desc(&desc, item->buffer, item->size);
o_mode = 0;
o_name = NULL;
@ -236,7 +241,7 @@ static int fsck_tree(struct tree *item)
if (strchr(name, '/'))
has_full_path = 1;
has_zero_pad |= *(char *)desc.buf == '0';
has_zero_pad |= *(char *)desc.buffer == '0';
update_tree_entry(&desc);
switch (mode) {
@ -346,8 +351,11 @@ static int fsck_tag(struct tag *tag)
static int fsck_sha1(unsigned char *sha1)
{
struct object *obj = parse_object(sha1);
if (!obj)
return error("%s: object corrupt or missing", sha1_to_hex(sha1));
if (!obj) {
errors_found |= ERROR_OBJECT;
return error("%s: object corrupt or missing",
sha1_to_hex(sha1));
}
if (obj->flags & SEEN)
return 0;
obj->flags |= SEEN;
@ -359,8 +367,10 @@ static int fsck_sha1(unsigned char *sha1)
return fsck_commit((struct commit *) obj);
if (obj->type == OBJ_TAG)
return fsck_tag((struct tag *) obj);
/* By now, parse_object() would've returned NULL instead. */
return objerror(obj, "unknown type '%d' (internal fsck error)", obj->type);
return objerror(obj, "unknown type '%d' (internal fsck error)",
obj->type);
}
/*
@ -546,7 +556,7 @@ static int fsck_head_link(void)
if (!head_points_at || !(flag & REF_ISSYMREF))
return error("HEAD is not a symbolic ref");
if (strncmp(head_points_at, "refs/heads/", 11))
if (prefixcmp(head_points_at, "refs/heads/"))
return error("HEAD points to something strange (%s)",
head_points_at);
if (is_null_sha1(sha1))
@ -576,11 +586,16 @@ static int fsck_cache_tree(struct cache_tree *it)
return err;
}
static const char fsck_usage[] =
"git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] "
"[--strict] <head-sha1>*]";
int cmd_fsck(int argc, char **argv, const char *prefix)
{
int i, heads;
track_object_refs = 1;
errors_found = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@ -610,7 +625,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
continue;
}
if (*arg == '-')
usage("git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] [--strict] <head-sha1>*]");
usage(fsck_usage);
}
fsck_head_link();
@ -632,7 +647,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
verify_pack(p, 0);
for (p = packed_git; p; p = p->next) {
int num = num_packed_objects(p);
uint32_t i, num = num_packed_objects(p);
for (i = 0; i < num; i++) {
unsigned char sha1[20];
nth_packed_object_sha1(p, i, sha1);
@ -690,5 +705,5 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
}
check_connectivity();
return 0;
return errors_found;
}

78
builtin-gc.c Normal file
View File

@ -0,0 +1,78 @@
/*
* git gc builtin command
*
* Cleanup unreachable files and optimize the repository.
*
* Copyright (c) 2007 James Bowes
*
* Based on git-gc.sh, which is
*
* Copyright (c) 2006 Shawn O. Pearce
*/
#include "cache.h"
#include "run-command.h"
#define FAILED_RUN "failed to run %s"
static const char builtin_gc_usage[] = "git-gc [--prune]";
static int pack_refs = -1;
static const char *argv_pack_refs[] = {"pack-refs", "--prune", NULL};
static const char *argv_reflog[] = {"reflog", "expire", "--all", NULL};
static const char *argv_repack[] = {"repack", "-a", "-d", "-l", NULL};
static const char *argv_prune[] = {"prune", NULL};
static const char *argv_rerere[] = {"rerere", "gc", NULL};
static int gc_config(const char *var, const char *value)
{
if (!strcmp(var, "gc.packrefs")) {
if (!strcmp(value, "notbare"))
pack_refs = -1;
else
pack_refs = git_config_bool(var, value);
return 0;
}
return git_default_config(var, value);
}
int cmd_gc(int argc, const char **argv, const char *prefix)
{
int i;
int prune = 0;
git_config(gc_config);
if (pack_refs < 0)
pack_refs = !is_bare_repository();
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--prune")) {
prune = 1;
continue;
}
/* perhaps other parameters later... */
break;
}
if (i != argc)
usage(builtin_gc_usage);
if (pack_refs && run_command_v_opt(argv_pack_refs, RUN_GIT_CMD))
return error(FAILED_RUN, argv_pack_refs[0]);
if (run_command_v_opt(argv_reflog, RUN_GIT_CMD))
return error(FAILED_RUN, argv_reflog[0]);
if (run_command_v_opt(argv_repack, RUN_GIT_CMD))
return error(FAILED_RUN, argv_repack[0]);
if (prune && run_command_v_opt(argv_prune, RUN_GIT_CMD))
return error(FAILED_RUN, argv_prune[0]);
if (run_command_v_opt(argv_rerere, RUN_GIT_CMD))
return error(FAILED_RUN, argv_rerere[0]);
return 0;
}

View File

@ -84,11 +84,11 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char
{
unsigned long size;
char *data;
char type[20];
enum object_type type;
char *to_free = NULL;
int hit;
data = read_sha1_file(sha1, type, &size);
data = read_sha1_file(sha1, &type, &size);
if (!data) {
error("'%s': unable to read %s", name, sha1_to_hex(sha1));
return 0;
@ -122,6 +122,8 @@ static int grep_file(struct grep_opt *opt, const char *filename)
struct stat st;
int i;
char *data;
size_t sz;
if (lstat(filename, &st) < 0) {
err_ret:
if (errno != ENOENT)
@ -132,11 +134,12 @@ static int grep_file(struct grep_opt *opt, const char *filename)
return 0; /* empty file -- no grep hit */
if (!S_ISREG(st.st_mode))
return 0;
sz = xsize_t(st.st_size);
i = open(filename, O_RDONLY);
if (i < 0)
goto err_ret;
data = xmalloc(st.st_size + 1);
if (st.st_size != read_in_full(i, data, st.st_size)) {
data = xmalloc(sz + 1);
if (st.st_size != read_in_full(i, data, sz)) {
error("'%s': short read %s", filename, strerror(errno));
close(i);
free(data);
@ -145,11 +148,12 @@ static int grep_file(struct grep_opt *opt, const char *filename)
close(i);
if (opt->relative && opt->prefix_length)
filename += opt->prefix_length;
i = grep_buffer(opt, filename, data, st.st_size);
i = grep_buffer(opt, filename, data, sz);
free(data);
return i;
}
#ifdef __unix__
static int exec_grep(int argc, const char **argv)
{
pid_t pid;
@ -298,6 +302,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
}
return hit;
}
#endif
static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
{
@ -373,21 +378,23 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
* decide if we want to descend into "abc"
* directory.
*/
strcpy(path_buf + len + entry.pathlen, "/");
strcpy(path_buf + len + tree_entry_len(entry.path, entry.sha1), "/");
if (!pathspec_matches(paths, down))
;
else if (S_ISREG(entry.mode))
hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len);
else if (S_ISDIR(entry.mode)) {
char type[20];
enum object_type type;
struct tree_desc sub;
void *data;
data = read_sha1_file(entry.sha1, type, &sub.size);
unsigned long size;
data = read_sha1_file(entry.sha1, &type, &size);
if (!data)
die("unable to read tree (%s)",
sha1_to_hex(entry.sha1));
sub.buf = data;
init_tree_desc(&sub, data, size);
hit |= grep_tree(opt, paths, &sub, tree_name, down);
free(data);
}
@ -403,12 +410,13 @@ static int grep_object(struct grep_opt *opt, const char **paths,
if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {
struct tree_desc tree;
void *data;
unsigned long size;
int hit;
data = read_object_with_reference(obj->sha1, tree_type,
&tree.size, NULL);
&size, NULL);
if (!data)
die("unable to read tree (%s)", sha1_to_hex(obj->sha1));
tree.buf = data;
init_tree_desc(&tree, data, size);
hit = grep_tree(opt, paths, &tree, name, "");
free(data);
return hit;
@ -426,6 +434,19 @@ static const char emsg_missing_context_len[] =
static const char emsg_missing_argument[] =
"option requires an argument -%s";
static int strtoul_ui(char const *s, unsigned int *result)
{
unsigned long ul;
char *p;
errno = 0;
ul = strtoul(s, &p, 10);
if (errno || *p || p == s || (unsigned int) ul != ul)
return -1;
*result = ul;
return 0;
}
int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
@ -527,9 +548,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.word_regexp = 1;
continue;
}
if (!strncmp("-A", arg, 2) ||
!strncmp("-B", arg, 2) ||
!strncmp("-C", arg, 2) ||
if (!prefixcmp(arg, "-A") ||
!prefixcmp(arg, "-B") ||
!prefixcmp(arg, "-C") ||
(arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) {
unsigned num;
const char *scan;
@ -548,7 +569,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
scan = arg + 1;
break;
}
if (sscanf(scan, "%u", &num) != 1)
if (strtoul_ui(scan, &num))
die(emsg_invalid_context_len, scan);
switch (arg[1]) {
case 'A':

View File

@ -283,11 +283,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++, argv++) {
const char *arg = argv[1];
if (!strncmp(arg, "--template=", 11))
if (!prefixcmp(arg, "--template="))
template_dir = arg+11;
else if (!strcmp(arg, "--shared"))
shared_repository = PERM_GROUP;
else if (!strncmp(arg, "--shared=", 9))
else if (!prefixcmp(arg, "--shared="))
shared_repository = git_config_perm("arg", arg+9);
else
usage(init_db_usage);

View File

@ -32,10 +32,10 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
rev->always_show_header = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strncmp(arg, "--encoding=", 11)) {
if (!prefixcmp(arg, "--encoding=")) {
arg += 11;
if (strcmp(arg, "none"))
git_log_output_encoding = strdup(arg);
git_log_output_encoding = xstrdup(arg);
else
git_log_output_encoding = "";
}
@ -89,8 +89,8 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
static int show_object(const unsigned char *sha1, int suppress_header)
{
unsigned long size;
char type[20];
char *buf = read_sha1_file(sha1, type, &size);
enum object_type type;
char *buf = read_sha1_file(sha1, &type, &size);
int offset = 0;
if (!buf)
@ -293,7 +293,7 @@ static int reopen_stdout(struct commit *commit, int nr, int keep_subject)
sol += 2;
/* strip [PATCH] or [PATCH blabla] */
if (!keep_subject && !strncmp(sol, "[PATCH", 6)) {
if (!keep_subject && !prefixcmp(sol, "[PATCH")) {
char *eos = strchr(sol + 6, ']');
if (eos) {
while (isspace(*eos))
@ -448,7 +448,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
else if (!strcmp(argv[i], "-n") ||
!strcmp(argv[i], "--numbered"))
numbered = 1;
else if (!strncmp(argv[i], "--start-number=", 15))
else if (!prefixcmp(argv[i], "--start-number="))
start_number = strtol(argv[i] + 15, NULL, 10);
else if (!strcmp(argv[i], "--start-number")) {
i++;
@ -482,15 +482,27 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
memcpy(add_signoff, committer, endpos - committer + 1);
add_signoff[endpos - committer + 1] = 0;
}
else if (!strcmp(argv[i], "--attach"))
else if (!strcmp(argv[i], "--attach")) {
rev.mime_boundary = git_version_string;
else if (!strncmp(argv[i], "--attach=", 9))
rev.no_inline = 1;
}
else if (!prefixcmp(argv[i], "--attach=")) {
rev.mime_boundary = argv[i] + 9;
rev.no_inline = 1;
}
else if (!strcmp(argv[i], "--inline")) {
rev.mime_boundary = git_version_string;
rev.no_inline = 0;
}
else if (!prefixcmp(argv[i], "--inline=")) {
rev.mime_boundary = argv[i] + 9;
rev.no_inline = 0;
}
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
ignore_if_in_upstream = 1;
else if (!strcmp(argv[i], "--thread"))
thread = 1;
else if (!strncmp(argv[i], "--in-reply-to=", 14))
else if (!prefixcmp(argv[i], "--in-reply-to="))
in_reply_to = argv[i] + 14;
else if (!strcmp(argv[i], "--in-reply-to")) {
i++;
@ -498,7 +510,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
die("Need a Message-Id for --in-reply-to");
in_reply_to = argv[i];
}
else if (!strncmp(argv[i], "--suffix=", 9))
else if (!prefixcmp(argv[i], "--suffix="))
fmt_patch_suffix = argv[i] + 9;
else
argv[j++] = argv[i];

View File

@ -406,7 +406,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
}
if (!strncmp(arg, "--exclude=", 10)) {
if (!prefixcmp(arg, "--exclude=")) {
exc_given = 1;
add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
@ -416,12 +416,12 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
add_excludes_from_file(&dir, argv[++i]);
continue;
}
if (!strncmp(arg, "--exclude-from=", 15)) {
if (!prefixcmp(arg, "--exclude-from=")) {
exc_given = 1;
add_excludes_from_file(&dir, arg+15);
continue;
}
if (!strncmp(arg, "--exclude-per-directory=", 24)) {
if (!prefixcmp(arg, "--exclude-per-directory=")) {
exc_given = 1;
dir.exclude_per_dir = arg + 24;
continue;
@ -434,7 +434,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
error_unmatch = 1;
continue;
}
if (!strncmp(arg, "--abbrev=", 9)) {
if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;

View File

@ -118,7 +118,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
chomp_prefix = 0;
break;
}
if (!strncmp(argv[1]+2, "abbrev=",7)) {
if (!prefixcmp(argv[1]+2, "abbrev=")) {
abbrev = strtoul(argv[1]+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;

View File

@ -11,19 +11,22 @@ static FILE *cmitmsg, *patchfile, *fin, *fout;
static int keep_subject;
static const char *metainfo_charset;
static char line[1000];
static char date[1000];
static char name[1000];
static char email[1000];
static char subject[1000];
static enum {
TE_DONTCARE, TE_QP, TE_BASE64,
} transfer_encoding;
static char charset[256];
static enum {
TYPE_TEXT, TYPE_OTHER,
} message_type;
static char multipart_boundary[1000];
static int multipart_boundary_len;
static char charset[256];
static int patch_lines;
static char **p_hdr_data, **s_hdr_data;
#define MAX_HDR_PARSED 10
#define MAX_BOUNDARIES 5
static char *sanity_check(char *name, char *email)
{
@ -137,15 +140,13 @@ static int handle_from(char *in_line)
return 1;
}
static int handle_date(char *line)
static int handle_header(char *line, char *data, int ofs)
{
strcpy(date, line);
return 0;
}
if (!line || !data)
return 1;
strcpy(data, line+ofs);
static int handle_subject(char *line)
{
strcpy(subject, line);
return 0;
}
@ -177,17 +178,32 @@ static int slurp_attr(const char *line, const char *name, char *attr)
return 1;
}
static int handle_subcontent_type(char *line)
struct content_type {
char *boundary;
int boundary_len;
};
static struct content_type content[MAX_BOUNDARIES];
static struct content_type *content_top = content;
static int handle_content_type(char *line)
{
/* We do not want to mess with boundary. Note that we do not
* handle nested multipart.
*/
if (strcasestr(line, "boundary=")) {
fprintf(stderr, "Not handling nested multipart message.\n");
exit(1);
char boundary[256];
if (strcasestr(line, "text/") == NULL)
message_type = TYPE_OTHER;
if (slurp_attr(line, "boundary=", boundary + 2)) {
memcpy(boundary, "--", 2);
if (content_top++ >= &content[MAX_BOUNDARIES]) {
fprintf(stderr, "Too many boundaries to handle\n");
exit(1);
}
content_top->boundary_len = strlen(boundary);
content_top->boundary = xmalloc(content_top->boundary_len+1);
strcpy(content_top->boundary, boundary);
}
slurp_attr(line, "charset=", charset);
if (*charset) {
if (slurp_attr(line, "charset=", charset)) {
int i, c;
for (i = 0; (c = charset[i]) != 0; i++)
charset[i] = tolower(c);
@ -195,17 +211,6 @@ static int handle_subcontent_type(char *line)
return 0;
}
static int handle_content_type(char *line)
{
*multipart_boundary = 0;
if (slurp_attr(line, "boundary=", multipart_boundary + 2)) {
memcpy(multipart_boundary, "--", 2);
multipart_boundary_len = strlen(multipart_boundary);
}
slurp_attr(line, "charset=", charset);
return 0;
}
static int handle_content_transfer_encoding(char *line)
{
if (strcasestr(line, "base64"))
@ -219,7 +224,7 @@ static int handle_content_transfer_encoding(char *line)
static int is_multipart_boundary(const char *line)
{
return (!memcmp(line, multipart_boundary, multipart_boundary_len));
return (!memcmp(line, content_top->boundary, content_top->boundary_len));
}
static int eatspace(char *line)
@ -230,62 +235,6 @@ static int eatspace(char *line)
return len;
}
#define SEEN_FROM 01
#define SEEN_DATE 02
#define SEEN_SUBJECT 04
#define SEEN_BOGUS_UNIX_FROM 010
#define SEEN_PREFIX 020
/* First lines of body can have From:, Date:, and Subject: or empty */
static void handle_inbody_header(int *seen, char *line)
{
if (*seen & SEEN_PREFIX)
return;
if (isspace(*line)) {
char *cp;
for (cp = line + 1; *cp; cp++) {
if (!isspace(*cp))
break;
}
if (!*cp)
return;
}
if (!memcmp(">From", line, 5) && isspace(line[5])) {
if (!(*seen & SEEN_BOGUS_UNIX_FROM)) {
*seen |= SEEN_BOGUS_UNIX_FROM;
return;
}
}
if (!memcmp("From:", line, 5) && isspace(line[5])) {
if (!(*seen & SEEN_FROM) && handle_from(line+6)) {
*seen |= SEEN_FROM;
return;
}
}
if (!memcmp("Date:", line, 5) && isspace(line[5])) {
if (!(*seen & SEEN_DATE)) {
handle_date(line+6);
*seen |= SEEN_DATE;
return;
}
}
if (!memcmp("Subject:", line, 8) && isspace(line[8])) {
if (!(*seen & SEEN_SUBJECT)) {
handle_subject(line+9);
*seen |= SEEN_SUBJECT;
return;
}
}
if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
if (!(*seen & SEEN_SUBJECT)) {
handle_subject(line);
*seen |= SEEN_SUBJECT;
return;
}
}
*seen |= SEEN_PREFIX;
}
static char *cleanup_subject(char *subject)
{
if (keep_subject)
@ -296,7 +245,7 @@ static char *cleanup_subject(char *subject)
switch (*subject) {
case 'r': case 'R':
if (!memcmp("e:", subject+1, 2)) {
subject +=3;
subject += 3;
continue;
}
break;
@ -341,57 +290,62 @@ static void cleanup_space(char *buf)
}
static void decode_header(char *it);
typedef int (*header_fn_t)(char *);
struct header_def {
const char *name;
header_fn_t func;
int namelen;
static char *header[MAX_HDR_PARSED] = {
"From","Subject","Date",
};
static void check_header(char *line, struct header_def *header)
static int check_header(char *line, char **hdr_data)
{
int i;
if (header[0].namelen <= 0) {
for (i = 0; header[i].name; i++)
header[i].namelen = strlen(header[i].name);
}
for (i = 0; header[i].name; i++) {
int len = header[i].namelen;
if (!strncasecmp(line, header[i].name, len) &&
/* search for the interesting parts */
for (i = 0; header[i]; i++) {
int len = strlen(header[i]);
if (!hdr_data[i] &&
!strncasecmp(line, header[i], len) &&
line[len] == ':' && isspace(line[len + 1])) {
/* Unwrap inline B and Q encoding, and optionally
* normalize the meta information to utf8.
*/
decode_header(line + len + 2);
header[i].func(line + len + 2);
break;
hdr_data[i] = xmalloc(1000 * sizeof(char));
if (! handle_header(line, hdr_data[i], len + 2)) {
return 1;
}
}
}
}
static void check_subheader_line(char *line)
{
static struct header_def header[] = {
{ "Content-Type", handle_subcontent_type },
{ "Content-Transfer-Encoding",
handle_content_transfer_encoding },
{ NULL },
};
check_header(line, header);
}
static void check_header_line(char *line)
{
static struct header_def header[] = {
{ "From", handle_from },
{ "Date", handle_date },
{ "Subject", handle_subject },
{ "Content-Type", handle_content_type },
{ "Content-Transfer-Encoding",
handle_content_transfer_encoding },
{ NULL },
};
check_header(line, header);
/* Content stuff */
if (!strncasecmp(line, "Content-Type", 12) &&
line[12] == ':' && isspace(line[12 + 1])) {
decode_header(line + 12 + 2);
if (! handle_content_type(line)) {
return 1;
}
}
if (!strncasecmp(line, "Content-Transfer-Encoding", 25) &&
line[25] == ':' && isspace(line[25 + 1])) {
decode_header(line + 25 + 2);
if (! handle_content_transfer_encoding(line)) {
return 1;
}
}
/* for inbody stuff */
if (!memcmp(">From", line, 5) && isspace(line[5]))
return 1;
if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
for (i = 0; header[i]; i++) {
if (!memcmp("Subject: ", header[i], 9)) {
if (! handle_header(line, hdr_data[i], 0)) {
return 1;
}
}
}
}
/* no match */
return 0;
}
static int is_rfc2822_header(char *line)
@ -545,10 +499,10 @@ static int decode_b_segment(char *in, char *ot, char *ep)
return 0;
}
static void convert_to_utf8(char *line, char *charset)
static void convert_to_utf8(char *line, const char *charset)
{
static char latin_one[] = "latin1";
char *input_charset = *charset ? charset : latin_one;
static const char latin_one[] = "latin1";
const char *input_charset = *charset ? charset : latin_one;
char *out = reencode_string(line, metainfo_charset, input_charset);
if (!out)
@ -647,39 +601,170 @@ static void decode_transfer_encoding(char *line)
}
}
static void handle_info(void)
static int handle_filter(char *line);
static int find_boundary(void)
{
char *sub;
sub = cleanup_subject(subject);
cleanup_space(name);
cleanup_space(date);
cleanup_space(email);
cleanup_space(sub);
fprintf(fout, "Author: %s\nEmail: %s\nSubject: %s\nDate: %s\n\n",
name, email, sub, date);
while(fgets(line, sizeof(line), fin) != NULL) {
if (is_multipart_boundary(line))
return 1;
}
return 0;
}
/* We are inside message body and have read line[] already.
* Spit out the commit log.
*/
static int handle_commit_msg(int *seen)
static int handle_boundary(void)
{
again:
if (!memcmp(line+content_top->boundary_len, "--", 2)) {
/* we hit an end boundary */
/* pop the current boundary off the stack */
free(content_top->boundary);
/* technically won't happen as is_multipart_boundary()
will fail first. But just in case..
*/
if (content_top-- < content) {
fprintf(stderr, "Detected mismatched boundaries, "
"can't recover\n");
exit(1);
}
handle_filter("\n");
/* skip to the next boundary */
if (!find_boundary())
return 0;
goto again;
}
/* set some defaults */
transfer_encoding = TE_DONTCARE;
charset[0] = 0;
message_type = TYPE_TEXT;
/* slurp in this section's info */
while (read_one_header_line(line, sizeof(line), fin))
check_header(line, p_hdr_data);
/* eat the blank line after section info */
return (fgets(line, sizeof(line), fin) != NULL);
}
static inline int patchbreak(const char *line)
{
/* Beginning of a "diff -" header? */
if (!memcmp("diff -", line, 6))
return 1;
/* CVS "Index: " line? */
if (!memcmp("Index: ", line, 7))
return 1;
/*
* "--- <filename>" starts patches without headers
* "---<sp>*" is a manual separator
*/
if (!memcmp("---", line, 3)) {
line += 3;
/* space followed by a filename? */
if (line[0] == ' ' && !isspace(line[1]))
return 1;
/* Just whitespace? */
for (;;) {
unsigned char c = *line++;
if (c == '\n')
return 1;
if (!isspace(c))
break;
}
return 0;
}
return 0;
}
static int handle_commit_msg(char *line)
{
static int still_looking = 1;
if (!cmitmsg)
return 0;
do {
if (!memcmp("diff -", line, 6) ||
!memcmp("---", line, 3) ||
!memcmp("Index: ", line, 7))
if (still_looking) {
char *cp = line;
if (isspace(*line)) {
for (cp = line + 1; *cp; cp++) {
if (!isspace(*cp))
break;
}
if (!*cp)
return 0;
}
if ((still_looking = check_header(cp, s_hdr_data)) != 0)
return 0;
}
if (patchbreak(line)) {
fclose(cmitmsg);
cmitmsg = NULL;
return 1;
}
fputs(line, cmitmsg);
return 0;
}
static int handle_patch(char *line)
{
fputs(line, patchfile);
patch_lines++;
return 0;
}
static int handle_filter(char *line)
{
static int filter = 0;
/* filter tells us which part we left off on
* a non-zero return indicates we hit a filter point
*/
switch (filter) {
case 0:
if (!handle_commit_msg(line))
break;
if ((multipart_boundary[0] && is_multipart_boundary(line))) {
/* We come here when the first part had only
* the commit message without any patch. We
* pretend we have not seen this line yet, and
* go back to the loop.
*/
return 1;
filter++;
case 1:
if (!handle_patch(line))
break;
filter++;
default:
return 1;
}
return 0;
}
static void handle_body(void)
{
int rc = 0;
static char newline[2000];
static char *np = newline;
/* Skip up to the first boundary */
if (content_top->boundary) {
if (!find_boundary())
return;
}
do {
/* process any boundary lines */
if (content_top->boundary && is_multipart_boundary(line)) {
/* flush any leftover */
if ((transfer_encoding == TE_BASE64) &&
(np != newline)) {
handle_filter(newline);
}
if (!handle_boundary())
return;
}
/* Unwrap transfer encoding and optionally
@ -689,105 +774,80 @@ static int handle_commit_msg(int *seen)
if (metainfo_charset)
convert_to_utf8(line, charset);
handle_inbody_header(seen, line);
if (!(*seen & SEEN_PREFIX))
switch (transfer_encoding) {
case TE_BASE64:
{
char *op = line;
/* binary data most likely doesn't have newlines */
if (message_type != TYPE_TEXT) {
rc = handle_filter(line);
break;
}
/* this is a decoded line that may contain
* multiple new lines. Pass only one chunk
* at a time to handle_filter()
*/
do {
while (*op != '\n' && *op != 0)
*np++ = *op++;
*np = *op;
if (*np != 0) {
/* should be sitting on a new line */
*(++np) = 0;
op++;
rc = handle_filter(newline);
np = newline;
}
} while (*op != 0);
/* the partial chunk is saved in newline and
* will be appended by the next iteration of fgets
*/
break;
}
default:
rc = handle_filter(line);
}
if (rc)
/* nothing left to filter */
break;
} while (fgets(line, sizeof(line), fin));
return;
}
static void handle_info(void)
{
char *sub;
char *hdr;
int i;
for (i = 0; header[i]; i++) {
/* only print inbody headers if we output a patch file */
if (patch_lines && s_hdr_data[i])
hdr = s_hdr_data[i];
else if (p_hdr_data[i])
hdr = p_hdr_data[i];
else
continue;
fputs(line, cmitmsg);
} while (fgets(line, sizeof(line), fin) != NULL);
fclose(cmitmsg);
cmitmsg = NULL;
return 0;
}
/* We have done the commit message and have the first
* line of the patch in line[].
*/
static void handle_patch(void)
{
do {
if (multipart_boundary[0] && is_multipart_boundary(line))
break;
/* Only unwrap transfer encoding but otherwise do not
* do anything. We do *NOT* want UTF-8 conversion
* here; we are dealing with the user payload.
*/
decode_transfer_encoding(line);
fputs(line, patchfile);
patch_lines++;
} while (fgets(line, sizeof(line), fin) != NULL);
}
/* multipart boundary and transfer encoding are set up for us, and we
* are at the end of the sub header. do equivalent of handle_body up
* to the next boundary without closing patchfile --- we will expect
* that the first part to contain commit message and a patch, and
* handle other parts as pure patches.
*/
static int handle_multipart_one_part(int *seen)
{
int n = 0;
while (fgets(line, sizeof(line), fin) != NULL) {
again:
n++;
if (is_multipart_boundary(line))
break;
if (handle_commit_msg(seen))
goto again;
handle_patch();
break;
}
if (n == 0)
return -1;
return 0;
}
static void handle_multipart_body(void)
{
int seen = 0;
int part_num = 0;
/* Skip up to the first boundary */
while (fgets(line, sizeof(line), fin) != NULL)
if (is_multipart_boundary(line)) {
part_num = 1;
break;
if (!memcmp(header[i], "Subject", 7)) {
sub = cleanup_subject(hdr);
cleanup_space(sub);
fprintf(fout, "Subject: %s\n", sub);
} else if (!memcmp(header[i], "From", 4)) {
handle_from(hdr);
fprintf(fout, "Author: %s\n", name);
fprintf(fout, "Email: %s\n", email);
} else {
cleanup_space(hdr);
fprintf(fout, "%s: %s\n", header[i], hdr);
}
if (!part_num)
return;
/* We are on boundary line. Start slurping the subhead. */
while (1) {
int hdr = read_one_header_line(line, sizeof(line), fin);
if (!hdr) {
if (handle_multipart_one_part(&seen) < 0)
return;
/* Reset per part headers */
transfer_encoding = TE_DONTCARE;
charset[0] = 0;
}
else
check_subheader_line(line);
}
fclose(patchfile);
if (!patch_lines) {
fprintf(stderr, "No patch found\n");
exit(1);
}
}
/* Non multipart message */
static void handle_body(void)
{
int seen = 0;
handle_commit_msg(&seen);
handle_patch();
fclose(patchfile);
if (!patch_lines) {
fprintf(stderr, "No patch found\n");
exit(1);
}
fprintf(fout, "\n");
}
int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
@ -809,18 +869,16 @@ int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
fclose(cmitmsg);
return -1;
}
while (1) {
int hdr = read_one_header_line(line, sizeof(line), fin);
if (!hdr) {
if (multipart_boundary[0])
handle_multipart_body();
else
handle_body();
handle_info();
break;
}
check_header_line(line);
}
p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
/* process the email header */
while (read_one_header_line(line, sizeof(line), fin))
check_header(line, p_hdr_data);
handle_body();
handle_info();
return 0;
}
@ -847,7 +905,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
metainfo_charset = def_charset;
else if (!strcmp(argv[1], "-n"))
metainfo_charset = NULL;
else if (!strncmp(argv[1], "--encoding=", 11))
else if (!prefixcmp(argv[1], "--encoding="))
metainfo_charset = argv[1] + 11;
else
usage(mailinfo_usage);

View File

@ -1,9 +1,7 @@
#include "cache.h"
#include "commit.h"
static int show_all;
static int merge_base(struct commit *rev1, struct commit *rev2)
static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_all)
{
struct commit_list *result = get_merge_bases(rev1, rev2, 0);
@ -23,16 +21,16 @@ static int merge_base(struct commit *rev1, struct commit *rev2)
static const char merge_base_usage[] =
"git-merge-base [--all] <commit-id> <commit-id>";
int main(int argc, char **argv)
int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
struct commit *rev1, *rev2;
unsigned char rev1key[20], rev2key[20];
int show_all = 0;
setup_git_directory();
git_config(git_default_config);
while (1 < argc && argv[1][0] == '-') {
char *arg = argv[1];
const char *arg = argv[1];
if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))
show_all = 1;
else
@ -49,5 +47,5 @@ int main(int argc, char **argv)
rev2 = lookup_commit_reference(rev2key);
if (!rev1 || !rev2)
return 1;
return merge_base(rev1, rev2);
return show_merge_base(rev1, rev2, show_all);
}

View File

@ -5,7 +5,7 @@
#include "refs.h"
static const char name_rev_usage[] =
"git-name-rev [--tags] ( --all | --stdin | committish [committish...] )\n";
"git-name-rev [--tags | --refs=<pattern>] ( --all | --stdin | committish [committish...] )\n";
typedef struct rev_name {
const char *tip_name;
@ -57,13 +57,17 @@ copy_data:
parents;
parents = parents->next, parent_number++) {
if (parent_number > 1) {
char *new_name = xmalloc(strlen(tip_name)+8);
int len = strlen(tip_name);
char *new_name = xmalloc(len + 8);
if (len > 2 && !strcmp(tip_name + len - 2, "^0"))
len -= 2;
if (generation > 0)
sprintf(new_name, "%s~%d^%d", tip_name,
sprintf(new_name, "%.*s~%d^%d", len, tip_name,
generation, parent_number);
else
sprintf(new_name, "%s^%d", tip_name, parent_number);
sprintf(new_name, "%.*s^%d", len, tip_name,
parent_number);
name_rev(parents->item, new_name,
merge_traversals + 1 , 0, 0);
@ -74,13 +78,21 @@ copy_data:
}
}
struct name_ref_data {
int tags_only;
const char *ref_filter;
};
static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data)
{
struct object *o = parse_object(sha1);
int tags_only = *(int*)cb_data;
struct name_ref_data *data = cb_data;
int deref = 0;
if (tags_only && strncmp(path, "refs/tags/", 10))
if (data->tags_only && prefixcmp(path, "refs/tags/"))
return 0;
if (data->ref_filter && fnmatch(data->ref_filter, path, 0))
return 0;
while (o && o->type == OBJ_TAG) {
@ -93,9 +105,9 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void
if (o && o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o;
if (!strncmp(path, "refs/heads/", 11))
if (!prefixcmp(path, "refs/heads/"))
path = path + 11;
else if (!strncmp(path, "refs/", 5))
else if (!prefixcmp(path, "refs/"))
path = path + 5;
name_rev(commit, xstrdup(path), 0, 0, deref);
@ -119,17 +131,22 @@ static const char* get_rev_name(struct object *o)
if (!n->generation)
return n->tip_name;
else {
int len = strlen(n->tip_name);
if (len > 2 && !strcmp(n->tip_name + len - 2, "^0"))
len -= 2;
snprintf(buffer, sizeof(buffer), "%.*s~%d", len, n->tip_name,
n->generation);
snprintf(buffer, sizeof(buffer), "%s~%d", n->tip_name, n->generation);
return buffer;
return buffer;
}
}
int cmd_name_rev(int argc, const char **argv, const char *prefix)
{
struct object_array revs = { 0, 0, NULL };
int as_is = 0, all = 0, transform_stdin = 0;
int tags_only = 0;
struct name_ref_data data = { 0, NULL };
git_config(git_default_config);
@ -146,7 +163,10 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
as_is = 1;
continue;
} else if (!strcmp(*argv, "--tags")) {
tags_only = 1;
data.tags_only = 1;
continue;
} else if (!prefixcmp(*argv, "--refs=")) {
data.ref_filter = *argv + 7;
continue;
} else if (!strcmp(*argv, "--all")) {
if (argc > 1)
@ -185,7 +205,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
add_object_array((struct object *)commit, *argv, &revs);
}
for_each_ref(name_ref, &tags_only);
for_each_ref(name_ref, &data);
if (transform_stdin) {
char buffer[2048];

View File

@ -23,7 +23,7 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\
struct object_entry {
unsigned char sha1[20];
unsigned long size; /* uncompressed size */
unsigned long offset; /* offset into the final pack file;
off_t offset; /* offset into the final pack file;
* nonzero if already written.
*/
unsigned int depth; /* delta depth */
@ -35,7 +35,7 @@ struct object_entry {
#define in_pack_header_size delta_size /* only when reusing pack data */
struct object_entry *delta; /* delta base object */
struct packed_git *in_pack; /* already in pack */
unsigned int in_pack_offset;
off_t in_pack_offset;
struct object_entry *delta_child; /* deltified objects who bases me */
struct object_entry *delta_sibling; /* other deltified objects who
* uses the same base as me
@ -68,7 +68,7 @@ static int allow_ofs_delta;
static struct object_entry **sorted_by_sha, **sorted_by_type;
static struct object_entry *objects;
static int nr_objects, nr_alloc, nr_result;
static uint32_t nr_objects, nr_alloc, nr_result;
static const char *base_name;
static unsigned char pack_file_sha1[20];
static int progress = 1;
@ -101,7 +101,7 @@ static int object_ix_hashsz;
* get the object sha1 from the main index.
*/
struct revindex_entry {
unsigned int offset;
off_t offset;
unsigned int nr;
};
struct pack_revindex {
@ -114,10 +114,8 @@ static int pack_revindex_hashsz;
/*
* stats
*/
static int written;
static int written_delta;
static int reused;
static int reused_delta;
static uint32_t written, written_delta;
static uint32_t reused, reused_delta;
static int pack_revindex_ix(struct packed_git *p)
{
@ -168,11 +166,12 @@ static void prepare_pack_revindex(struct pack_revindex *rix)
struct packed_git *p = rix->p;
int num_ent = num_packed_objects(p);
int i;
void *index = p->index_base + 256;
const char *index = p->index_data;
index += 4 * 256;
rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1));
for (i = 0; i < num_ent; i++) {
unsigned int hl = *((unsigned int *)((char *) index + 24*i));
uint32_t hl = *((uint32_t *)(index + 24 * i));
rix->revindex[i].offset = ntohl(hl);
rix->revindex[i].nr = i;
}
@ -185,7 +184,7 @@ static void prepare_pack_revindex(struct pack_revindex *rix)
}
static struct revindex_entry * find_packed_object(struct packed_git *p,
unsigned int ofs)
off_t ofs)
{
int num;
int lo, hi;
@ -213,25 +212,24 @@ static struct revindex_entry * find_packed_object(struct packed_git *p,
die("internal error: pack revindex corrupt");
}
static unsigned long find_packed_object_size(struct packed_git *p,
unsigned long ofs)
static off_t find_packed_object_size(struct packed_git *p, off_t ofs)
{
struct revindex_entry *entry = find_packed_object(p, ofs);
return entry[1].offset - ofs;
}
static unsigned char *find_packed_object_name(struct packed_git *p,
unsigned long ofs)
static const unsigned char *find_packed_object_name(struct packed_git *p,
off_t ofs)
{
struct revindex_entry *entry = find_packed_object(p, ofs);
return (unsigned char *)(p->index_base + 256) + 24 * entry->nr + 4;
return ((unsigned char *)p->index_data) + 4 * 256 + 24 * entry->nr + 4;
}
static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
{
unsigned long othersize, delta_size;
char type[10];
void *otherbuf = read_sha1_file(entry->delta->sha1, type, &othersize);
enum object_type type;
void *otherbuf = read_sha1_file(entry->delta->sha1, &type, &othersize);
void *delta_buf;
if (!otherbuf)
@ -278,8 +276,8 @@ static int encode_header(enum object_type type, unsigned long size, unsigned cha
*/
static int check_pack_inflate(struct packed_git *p,
struct pack_window **w_curs,
unsigned long offset,
unsigned long len,
off_t offset,
off_t len,
unsigned long expect)
{
z_stream stream;
@ -305,8 +303,8 @@ static int check_pack_inflate(struct packed_git *p,
static void copy_pack_data(struct sha1file *f,
struct packed_git *p,
struct pack_window **w_curs,
unsigned long offset,
unsigned long len)
off_t offset,
off_t len)
{
unsigned char *in;
unsigned int avail;
@ -314,7 +312,7 @@ static void copy_pack_data(struct sha1file *f,
while (len) {
in = use_pack(p, w_curs, offset, &avail);
if (avail > len)
avail = len;
avail = (unsigned int)len;
sha1write(f, in, avail);
offset += avail;
len -= avail;
@ -371,14 +369,15 @@ static int revalidate_loose_object(struct object_entry *entry,
return check_loose_inflate(map, mapsize, size);
}
static unsigned long write_object(struct sha1file *f,
static off_t write_object(struct sha1file *f,
struct object_entry *entry)
{
unsigned long size;
char type[10];
enum object_type type;
void *buf;
unsigned char header[10];
unsigned hdrlen, datalen;
unsigned hdrlen;
off_t datalen;
enum object_type obj_type;
int to_reuse = 0;
@ -416,7 +415,7 @@ static unsigned long write_object(struct sha1file *f,
}
if (!to_reuse) {
buf = read_sha1_file(entry->sha1, type, &size);
buf = read_sha1_file(entry->sha1, &type, &size);
if (!buf)
die("unable to read %s", sha1_to_hex(entry->sha1));
if (size != entry->size)
@ -441,7 +440,7 @@ static unsigned long write_object(struct sha1file *f,
* encoding of the relative offset for the delta
* base from this object's position in the pack.
*/
unsigned long ofs = entry->offset - entry->delta->offset;
off_t ofs = entry->offset - entry->delta->offset;
unsigned pos = sizeof(header) - 1;
header[pos] = ofs & 127;
while (ofs >>= 7)
@ -462,7 +461,7 @@ static unsigned long write_object(struct sha1file *f,
else {
struct packed_git *p = entry->in_pack;
struct pack_window *w_curs = NULL;
unsigned long offset;
off_t offset;
if (entry->delta) {
obj_type = (allow_ofs_delta && entry->delta->offset) ?
@ -472,7 +471,7 @@ static unsigned long write_object(struct sha1file *f,
hdrlen = encode_header(obj_type, entry->size, header);
sha1write(f, header, hdrlen);
if (obj_type == OBJ_OFS_DELTA) {
unsigned long ofs = entry->offset - entry->delta->offset;
off_t ofs = entry->offset - entry->delta->offset;
unsigned pos = sizeof(header) - 1;
header[pos] = ofs & 127;
while (ofs >>= 7)
@ -500,9 +499,9 @@ static unsigned long write_object(struct sha1file *f,
return hdrlen + datalen;
}
static unsigned long write_one(struct sha1file *f,
static off_t write_one(struct sha1file *f,
struct object_entry *e,
unsigned long offset)
off_t offset)
{
if (e->offset || e->preferred_base)
/* offset starts from header size and cannot be zero
@ -518,9 +517,9 @@ static unsigned long write_one(struct sha1file *f,
static void write_pack_file(void)
{
int i;
uint32_t i;
struct sha1file *f;
unsigned long offset;
off_t offset;
struct pack_header hdr;
unsigned last_percent = 999;
int do_progress = progress;
@ -533,7 +532,7 @@ static void write_pack_file(void)
f = sha1create("%s-%s.%s", base_name,
sha1_to_hex(object_list_sha1), "pack");
if (do_progress)
fprintf(stderr, "Writing %d objects.\n", nr_result);
fprintf(stderr, "Writing %u objects.\n", nr_result);
hdr.hdr_signature = htonl(PACK_SIGNATURE);
hdr.hdr_version = htonl(PACK_VERSION);
@ -558,13 +557,13 @@ static void write_pack_file(void)
fputc('\n', stderr);
done:
if (written != nr_result)
die("wrote %d objects while expecting %d", written, nr_result);
die("wrote %u objects while expecting %u", written, nr_result);
sha1close(f, pack_file_sha1, 1);
}
static void write_index_file(void)
{
int i;
uint32_t i;
struct sha1file *f = sha1create("%s-%s.%s", base_name,
sha1_to_hex(object_list_sha1), "idx");
struct object_entry **list = sorted_by_sha;
@ -633,7 +632,7 @@ static struct object_entry *locate_object_entry(const unsigned char *sha1)
static void rehash_objects(void)
{
int i;
uint32_t i;
struct object_entry *oe;
object_ix_hashsz = nr_objects * 3;
@ -670,16 +669,16 @@ static unsigned name_hash(const char *name)
static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclude)
{
unsigned int idx = nr_objects;
uint32_t idx = nr_objects;
struct object_entry *entry;
struct packed_git *p;
unsigned int found_offset = 0;
off_t found_offset = 0;
struct packed_git *found_pack = NULL;
int ix, status = 0;
if (!exclude) {
for (p = packed_git; p; p = p->next) {
unsigned long offset = find_pack_entry_one(sha1, p);
off_t offset = find_pack_entry_one(sha1, p);
if (offset) {
if (incremental)
return 0;
@ -696,9 +695,8 @@ static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclud
goto already_added;
if (idx >= nr_alloc) {
unsigned int needed = (idx + 1024) * 3 / 2;
objects = xrealloc(objects, needed * sizeof(*entry));
nr_alloc = needed;
nr_alloc = (idx + 1024) * 3 / 2;
objects = xrealloc(objects, nr_alloc * sizeof(*entry));
}
entry = objects + idx;
nr_objects = idx + 1;
@ -718,7 +716,7 @@ static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclud
already_added:
if (progress_update) {
fprintf(stderr, "Counting objects...%d\r", nr_objects);
fprintf(stderr, "Counting objects...%u\r", nr_objects);
progress_update = 0;
}
if (exclude)
@ -765,7 +763,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
struct pbase_tree_cache *ent, *nent;
void *data;
unsigned long size;
char type[20];
enum object_type type;
int neigh;
int my_ix = pbase_tree_cache_ix(sha1);
int available_ix = -1;
@ -792,10 +790,10 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
/* Did not find one. Either we got a bogus request or
* we need to read and perhaps cache.
*/
data = read_sha1_file(sha1, type, &size);
data = read_sha1_file(sha1, &type, &size);
if (!data)
return NULL;
if (strcmp(type, tree_type)) {
if (type != OBJ_TREE) {
free(data);
return NULL;
}
@ -854,19 +852,19 @@ static void add_pbase_object(struct tree_desc *tree,
while (tree_entry(tree,&entry)) {
unsigned long size;
char type[20];
enum object_type type;
if (entry.pathlen != cmplen ||
if (tree_entry_len(entry.path, entry.sha1) != cmplen ||
memcmp(entry.path, name, cmplen) ||
!has_sha1_file(entry.sha1) ||
sha1_object_info(entry.sha1, type, &size))
(type = sha1_object_info(entry.sha1, &size)) < 0)
continue;
if (name[cmplen] != '/') {
unsigned hash = name_hash(fullname);
add_object_entry(entry.sha1, hash, 1);
return;
}
if (!strcmp(type, tree_type)) {
if (type == OBJ_TREE) {
struct tree_desc sub;
struct pbase_tree_cache *tree;
const char *down = name+cmplen+1;
@ -875,8 +873,7 @@ static void add_pbase_object(struct tree_desc *tree,
tree = pbase_tree_get(entry.sha1);
if (!tree)
return;
sub.buf = tree->tree_data;
sub.size = tree->tree_size;
init_tree_desc(&sub, tree->tree_data, tree->tree_size);
add_pbase_object(&sub, down, downlen, fullname);
pbase_tree_put(tree);
@ -939,8 +936,7 @@ static void add_preferred_base_object(const char *name, unsigned hash)
}
else {
struct tree_desc tree;
tree.buf = it->pcache.tree_data;
tree.size = it->pcache.tree_size;
init_tree_desc(&tree, it->pcache.tree_data, it->pcache.tree_size);
add_pbase_object(&tree, name, cmplen, name);
}
}
@ -978,22 +974,20 @@ static void add_preferred_base(unsigned char *sha1)
static void check_object(struct object_entry *entry)
{
char type[20];
if (entry->in_pack && !entry->preferred_base) {
struct packed_git *p = entry->in_pack;
struct pack_window *w_curs = NULL;
unsigned long left = p->pack_size - entry->in_pack_offset;
unsigned long size, used;
unsigned int avail;
unsigned char *buf;
struct object_entry *base_entry = NULL;
buf = use_pack(p, &w_curs, entry->in_pack_offset, NULL);
buf = use_pack(p, &w_curs, entry->in_pack_offset, &avail);
/* We want in_pack_type even if we do not reuse delta.
* There is no point not reusing non-delta representations.
*/
used = unpack_object_header_gently(buf, left,
used = unpack_object_header_gently(buf, avail,
&entry->in_pack_type, &size);
/* Check if it is delta, and the base is also an object
@ -1001,8 +995,9 @@ static void check_object(struct object_entry *entry)
* delta.
*/
if (!no_reuse_delta) {
unsigned char c, *base_name;
unsigned long ofs;
unsigned char c;
const unsigned char *base_name;
off_t ofs;
unsigned long used_0;
/* there is at least 20 bytes left in the pack */
switch (entry->in_pack_type) {
@ -1062,21 +1057,10 @@ static void check_object(struct object_entry *entry)
/* Otherwise we would do the usual */
}
if (sha1_object_info(entry->sha1, type, &entry->size))
entry->type = sha1_object_info(entry->sha1, &entry->size);
if (entry->type < 0)
die("unable to get type of object %s",
sha1_to_hex(entry->sha1));
if (!strcmp(type, commit_type)) {
entry->type = OBJ_COMMIT;
} else if (!strcmp(type, tree_type)) {
entry->type = OBJ_TREE;
} else if (!strcmp(type, blob_type)) {
entry->type = OBJ_BLOB;
} else if (!strcmp(type, tag_type)) {
entry->type = OBJ_TAG;
} else
die("unable to pack object %s of type %s",
sha1_to_hex(entry->sha1), type);
}
static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
@ -1094,7 +1078,7 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
static void get_object_details(void)
{
int i;
uint32_t i;
struct object_entry *entry;
prepare_pack_ix();
@ -1133,7 +1117,7 @@ static int sort_comparator(const void *_a, const void *_b)
static struct object_entry **create_sorted_list(entry_sort_t sort)
{
struct object_entry **list = xmalloc(nr_objects * sizeof(struct object_entry *));
int i;
uint32_t i;
for (i = 0; i < nr_objects; i++)
list[i] = objects + i;
@ -1150,7 +1134,7 @@ static int sha1_sort(const struct object_entry *a, const struct object_entry *b)
static struct object_entry **create_final_object_list(void)
{
struct object_entry **list;
int i, j;
uint32_t i, j;
for (i = nr_result = 0; i < nr_objects; i++)
if (!objects[i].preferred_base)
@ -1206,7 +1190,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
struct object_entry *trg_entry = trg->entry;
struct object_entry *src_entry = src->entry;
unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;
char type[10];
enum object_type type;
void *delta_buf;
/* Don't bother doing diffs between different types */
@ -1257,13 +1241,13 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
/* Load data if not already done */
if (!trg->data) {
trg->data = read_sha1_file(trg_entry->sha1, type, &sz);
trg->data = read_sha1_file(trg_entry->sha1, &type, &sz);
if (sz != trg_size)
die("object %s inconsistent object length (%lu vs %lu)",
sha1_to_hex(trg_entry->sha1), sz, trg_size);
}
if (!src->data) {
src->data = read_sha1_file(src_entry->sha1, type, &sz);
src->data = read_sha1_file(src_entry->sha1, &type, &sz);
if (sz != src_size)
die("object %s inconsistent object length (%lu vs %lu)",
sha1_to_hex(src_entry->sha1), sz, src_size);
@ -1292,20 +1276,20 @@ static void progress_interval(int signum)
static void find_deltas(struct object_entry **list, int window, int depth)
{
int i, idx;
uint32_t i = nr_objects, idx = 0, processed = 0;
unsigned int array_size = window * sizeof(struct unpacked);
struct unpacked *array = xmalloc(array_size);
unsigned processed = 0;
struct unpacked *array;
unsigned last_percent = 999;
if (!nr_objects)
return;
array = xmalloc(array_size);
memset(array, 0, array_size);
i = nr_objects;
idx = 0;
if (progress)
fprintf(stderr, "Deltifying %d objects.\n", nr_result);
fprintf(stderr, "Deltifying %u objects.\n", nr_result);
while (--i >= 0) {
struct object_entry *entry = list[i];
do {
struct object_entry *entry = list[--i];
struct unpacked *n = array + idx;
int j;
@ -1338,7 +1322,7 @@ static void find_deltas(struct object_entry **list, int window, int depth)
j = window;
while (--j > 0) {
unsigned int other_idx = idx + j;
uint32_t other_idx = idx + j;
struct unpacked *m;
if (other_idx >= window)
other_idx -= window;
@ -1358,7 +1342,7 @@ static void find_deltas(struct object_entry **list, int window, int depth)
idx++;
if (idx >= window)
idx = 0;
}
} while (i > 0);
if (progress)
fputc('\n', stderr);
@ -1399,7 +1383,7 @@ static int reuse_cached_pack(unsigned char *sha1)
}
if (progress)
fprintf(stderr, "Reusing %d objects pack %s\n", nr_objects,
fprintf(stderr, "Reusing %u objects pack %s\n", nr_objects,
sha1_to_hex(sha1));
if (pack_to_stdout) {
@ -1550,7 +1534,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
struct object_entry **list;
int use_internal_rev_list = 0;
int thin = 0;
int i;
uint32_t i;
const char **rp_av;
int rp_ac_alloc = 64;
int rp_ac;
@ -1582,14 +1566,14 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
incremental = 1;
continue;
}
if (!strncmp("--window=", arg, 9)) {
if (!prefixcmp(arg, "--window=")) {
char *end;
window = strtoul(arg+9, &end, 0);
if (!arg[9] || *end)
usage(pack_usage);
continue;
}
if (!strncmp("--depth=", arg, 8)) {
if (!prefixcmp(arg, "--depth=")) {
char *end;
depth = strtoul(arg+8, &end, 0);
if (!arg[8] || *end)
@ -1625,7 +1609,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp("--unpacked", arg) ||
!strncmp("--unpacked=", arg, 11) ||
!prefixcmp(arg, "--unpacked=") ||
!strcmp("--reflog", arg) ||
!strcmp("--all", arg)) {
use_internal_rev_list = 1;
@ -1683,7 +1667,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
}
if (progress)
fprintf(stderr, "Done counting %d objects.\n", nr_objects);
fprintf(stderr, "Done counting %u objects.\n", nr_objects);
sorted_by_sha = create_final_object_list();
if (non_empty && !nr_result)
return 0;
@ -1696,7 +1680,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
}
SHA1_Final(object_list_sha1, &ctx);
if (progress && (nr_objects != nr_result))
fprintf(stderr, "Result has %d objects.\n", nr_result);
fprintf(stderr, "Result has %u objects.\n", nr_result);
if (reuse_cached_pack(object_list_sha1))
;
@ -1717,7 +1701,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
}
}
if (progress)
fprintf(stderr, "Total %d (delta %d), reused %d (delta %d)\n",
fprintf(stderr, "Total %u (delta %u), reused %u (delta %u)\n",
written, written_delta, reused, reused_delta);
return 0;
}

View File

@ -36,7 +36,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
/* Do not pack the symbolic refs */
if ((flags & REF_ISSYMREF))
return 0;
is_tag_ref = !strncmp(path, "refs/tags/", 10);
is_tag_ref = !prefixcmp(path, "refs/tags/");
/* ALWAYS pack refs that were already packed or are tags */
if (!cb->all && !is_tag_ref && !(flags & REF_ISPACKED))

View File

@ -10,19 +10,12 @@ static int show_only;
static int prune_object(char *path, const char *filename, const unsigned char *sha1)
{
char buf[20];
const char *type;
if (show_only) {
if (sha1_object_info(sha1, buf, NULL))
type = "unknown";
else
type = buf;
printf("%s %s\n", sha1_to_hex(sha1), type);
return 0;
}
unlink(mkpath("%s/%s", path, filename));
rmdir(path);
enum object_type type = sha1_object_info(sha1, NULL);
printf("%s %s\n", sha1_to_hex(sha1),
(type > 0) ? typename(type) : "unknown");
} else
unlink(mkpath("%s/%s", path, filename));
return 0;
}
@ -65,6 +58,8 @@ static int prune_dir(int i, char *path)
}
fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
}
if (!show_only)
rmdir(path);
closedir(dir);
return 0;
}

View File

@ -32,7 +32,7 @@ static int expand_one_ref(const char *ref, const unsigned char *sha1, int flag,
/* Ignore the "refs/" at the beginning of the refname */
ref += 5;
if (!strncmp(ref, "tags/", 5))
if (!prefixcmp(ref, "tags/"))
add_refspec(xstrdup(ref));
return 0;
}
@ -149,10 +149,10 @@ static int get_remotes_uri(const char *repo, const char *uri[MAX_URI])
int is_refspec;
char *s, *p;
if (!strncmp("URL:", buffer, 4)) {
if (!prefixcmp(buffer, "URL:")) {
is_refspec = 0;
s = buffer + 4;
} else if (!strncmp("Push:", buffer, 5)) {
} else if (!prefixcmp(buffer, "Push:")) {
is_refspec = 1;
s = buffer + 5;
} else
@ -195,7 +195,7 @@ static int config_get_receivepack;
static int get_remote_config(const char* key, const char* value)
{
if (!strncmp(key, "remote.", 7) &&
if (!prefixcmp(key, "remote.") &&
!strncmp(key + 7, config_repo, config_repo_len)) {
if (!strcmp(key + 7 + config_repo_len, ".url")) {
if (config_current_uri < MAX_URI)
@ -323,10 +323,10 @@ static int do_push(const char *repo)
int dest_refspec_nr = refspec_nr;
const char **dest_refspec = refspec;
const char *dest = uri[i];
const char *sender = "git-send-pack";
if (!strncmp(dest, "http://", 7) ||
!strncmp(dest, "https://", 8))
sender = "git-http-push";
const char *sender = "send-pack";
if (!prefixcmp(dest, "http://") ||
!prefixcmp(dest, "https://"))
sender = "http-push";
else if (thin)
argv[dest_argc++] = "--thin";
argv[0] = sender;
@ -336,7 +336,7 @@ static int do_push(const char *repo)
argv[dest_argc] = NULL;
if (verbose)
fprintf(stderr, "Pushing to %s\n", dest);
err = run_command_v(argv);
err = run_command_v_opt(argv, RUN_GIT_CMD);
if (!err)
continue;
switch (err) {
@ -373,7 +373,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
verbose=1;
continue;
}
if (!strncmp(arg, "--repo=", 7)) {
if (!prefixcmp(arg, "--repo=")) {
repo = arg+7;
continue;
}
@ -397,11 +397,11 @@ int cmd_push(int argc, const char **argv, const char *prefix)
thin = 0;
continue;
}
if (!strncmp(arg, "--receive-pack=", 15)) {
if (!prefixcmp(arg, "--receive-pack=")) {
receivepack = arg;
continue;
}
if (!strncmp(arg, "--exec=", 7)) {
if (!prefixcmp(arg, "--exec=")) {
receivepack = arg;
continue;
}

View File

@ -55,8 +55,7 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
int cnt;
hashcpy(it->sha1, tree->object.sha1);
desc.buf = tree->buffer;
desc.size = tree->size;
init_tree_desc(&desc, tree->buffer, tree->size);
cnt = 0;
while (tree_entry(&desc, &entry)) {
if (!S_ISDIR(entry.mode))
@ -133,7 +132,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
* entries and put the entries from the tree under the
* given subdirectory.
*/
if (!strncmp(arg, "--prefix=", 9)) {
if (!prefixcmp(arg, "--prefix=")) {
if (stage || opts.merge || opts.prefix)
usage(read_tree_usage);
opts.prefix = arg + 9;
@ -179,13 +178,13 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
continue;
}
if (!strncmp(arg, "--exclude-per-directory=", 24)) {
if (!prefixcmp(arg, "--exclude-per-directory=")) {
struct dir_struct *dir;
if (opts.dir)
die("more than one --exclude-per-directory are given.");
dir = calloc(1, sizeof(*opts.dir));
dir = xcalloc(1, sizeof(*opts.dir));
dir->show_ignored = 1;
dir->exclude_per_dir = arg + 24;
opts.dir = dir;

View File

@ -52,18 +52,18 @@ static int tree_is_complete(const unsigned char *sha1)
if (tree->object.flags & INCOMPLETE)
return 0;
desc.buf = tree->buffer;
desc.size = tree->size;
if (!desc.buf) {
char type[20];
void *data = read_sha1_file(sha1, type, &desc.size);
if (!tree->buffer) {
enum object_type type;
unsigned long size;
void *data = read_sha1_file(sha1, &type, &size);
if (!data) {
tree->object.flags |= INCOMPLETE;
return 0;
}
desc.buf = data;
tree->buffer = data;
tree->size = size;
}
init_tree_desc(&desc, tree->buffer, tree->size);
complete = 1;
while (tree_entry(&desc, &entry)) {
if (!has_sha1_file(entry.sha1) ||
@ -215,8 +215,8 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
old = lookup_commit_reference_gently(osha1, 1);
if (!new && !is_null_sha1(nsha1))
new = lookup_commit_reference_gently(nsha1, 1);
if ((old && !in_merge_bases(old, cb->ref_commit)) ||
(new && !in_merge_bases(new, cb->ref_commit)))
if ((old && !in_merge_bases(old, &cb->ref_commit, 1)) ||
(new && !in_merge_bases(new, &cb->ref_commit, 1)))
goto prune;
}
@ -321,9 +321,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
const char *arg = argv[i];
if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
cb.dry_run = 1;
else if (!strncmp(arg, "--expire=", 9))
else if (!prefixcmp(arg, "--expire="))
cb.expire_total = approxidate(arg + 9);
else if (!strncmp(arg, "--expire-unreachable=", 21))
else if (!prefixcmp(arg, "--expire-unreachable="))
cb.expire_unreachable = approxidate(arg + 21);
else if (!strcmp(arg, "--stale-fix"))
cb.stalefix = 1;

View File

@ -105,11 +105,11 @@ static int handle_file(const char *path,
SHA1_Init(&ctx);
while (fgets(buf, sizeof(buf), f)) {
if (!strncmp("<<<<<<< ", buf, 8))
if (!prefixcmp(buf, "<<<<<<< "))
hunk = 1;
else if (!strncmp("=======", buf, 7))
else if (!prefixcmp(buf, "======="))
hunk = 2;
else if (!strncmp(">>>>>>> ", buf, 8)) {
else if (!prefixcmp(buf, ">>>>>>> ")) {
hunk_no++;
hunk = 0;
if (memcmp(one->ptr, two->ptr, one->nr < two->nr ?

View File

@ -180,7 +180,7 @@ static struct commit_list *find_bisection(struct commit_list *list)
nr++;
p = p->next;
}
closest = 0;
closest = -1;
best = list;
for (p = list; p; p = p->next) {

View File

@ -233,7 +233,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
continue;
}
if (!strncmp(arg,"-n",2)) {
if (!prefixcmp(arg, "-n")) {
if ((filter & DO_FLAGS) && (filter & DO_REVS))
show(arg);
continue;
@ -274,7 +274,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--short") ||
!strncmp(arg, "--short=", 8)) {
!prefixcmp(arg, "--short=")) {
filter &= ~(DO_FLAGS|DO_NOREV);
verify = 1;
abbrev = DEFAULT_ABBREV;
@ -352,19 +352,19 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
: "false");
continue;
}
if (!strncmp(arg, "--since=", 8)) {
if (!prefixcmp(arg, "--since=")) {
show_datestring("--max-age=", arg+8);
continue;
}
if (!strncmp(arg, "--after=", 8)) {
if (!prefixcmp(arg, "--after=")) {
show_datestring("--max-age=", arg+8);
continue;
}
if (!strncmp(arg, "--before=", 9)) {
if (!prefixcmp(arg, "--before=")) {
show_datestring("--min-age=", arg+9);
continue;
}
if (!strncmp(arg, "--until=", 8)) {
if (!prefixcmp(arg, "--until=")) {
show_datestring("--min-age=", arg+8);
continue;
}

404
builtin-revert.c Normal file
View File

@ -0,0 +1,404 @@
#include "cache.h"
#include "builtin.h"
#include "object.h"
#include "commit.h"
#include "tag.h"
#include "wt-status.h"
#include "run-command.h"
#include "exec_cmd.h"
#include "utf8.h"
/*
* This implements the builtins revert and cherry-pick.
*
* Copyright (c) 2007 Johannes E. Schindelin
*
* Based on git-revert.sh, which is
*
* Copyright (c) 2005 Linus Torvalds
* Copyright (c) 2005 Junio C Hamano
*/
static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] <commit-ish>";
static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] <commit-ish>";
static int edit;
static int replay;
enum { REVERT, CHERRY_PICK } action;
static int no_commit;
static struct commit *commit;
static int needed_deref;
static const char *me;
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
static void parse_options(int argc, const char **argv)
{
const char *usage_str = action == REVERT ?
revert_usage : cherry_pick_usage;
unsigned char sha1[20];
const char *arg;
int i;
if (argc < 2)
usage(usage_str);
for (i = 1; i < argc - 1; i++) {
arg = argv[i];
if (!strcmp(arg, "-n") || !strcmp(arg, "--no-commit"))
no_commit = 1;
else if (!strcmp(arg, "-e") || !strcmp(arg, "--edit"))
edit = 1;
else if (!strcmp(arg, "--no-edit"))
edit = 0;
else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-"
"to-expose-my-private-commit-object-name"))
replay = 0;
else if (strcmp(arg, "-r"))
usage(usage_str);
}
arg = argv[argc - 1];
if (get_sha1(arg, sha1))
die ("Cannot find '%s'", arg);
commit = (struct commit *)parse_object(sha1);
if (!commit)
die ("Could not find %s", sha1_to_hex(sha1));
if (commit->object.type == OBJ_TAG) {
commit = (struct commit *)
deref_tag((struct object *)commit, arg, strlen(arg));
needed_deref = 1;
}
if (commit->object.type != OBJ_COMMIT)
die ("'%s' does not point to a commit", arg);
}
static char *get_oneline(const char *message)
{
char *result;
const char *p = message, *abbrev, *eol;
int abbrev_len, oneline_len;
if (!p)
die ("Could not read commit message of %s",
sha1_to_hex(commit->object.sha1));
while (*p && (*p != '\n' || p[1] != '\n'))
p++;
if (*p) {
p += 2;
for (eol = p + 1; *eol && *eol != '\n'; eol++)
; /* do nothing */
} else
eol = p;
abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
abbrev_len = strlen(abbrev);
oneline_len = eol - p;
result = xmalloc(abbrev_len + 5 + oneline_len);
memcpy(result, abbrev, abbrev_len);
memcpy(result + abbrev_len, "... ", 4);
memcpy(result + abbrev_len + 4, p, oneline_len);
result[abbrev_len + 4 + oneline_len] = '\0';
return result;
}
char *get_encoding(const char *message)
{
const char *p = message, *eol;
if (!p)
die ("Could not read commit message of %s",
sha1_to_hex(commit->object.sha1));
while (*p && *p != '\n') {
for (eol = p + 1; *eol && *eol != '\n'; eol++)
; /* do nothing */
if (!prefixcmp(p, "encoding ")) {
char *result = xmalloc(eol - 8 - p);
strlcpy(result, p + 9, eol - 8 - p);
return result;
}
p = eol;
if (*p == '\n')
p++;
}
return NULL;
}
struct lock_file msg_file;
static int msg_fd;
static void add_to_msg(const char *string)
{
int len = strlen(string);
if (write_in_full(msg_fd, string, len) < 0)
die ("Could not write to .msg");
}
static void add_message_to_msg(const char *message)
{
const char *p = message;
while (*p && (*p != '\n' || p[1] != '\n'))
p++;
if (!*p)
add_to_msg(sha1_to_hex(commit->object.sha1));
p += 2;
add_to_msg(p);
return;
}
static void set_author_ident_env(const char *message)
{
const char *p = message;
if (!p)
die ("Could not read commit message of %s",
sha1_to_hex(commit->object.sha1));
while (*p && *p != '\n') {
const char *eol;
for (eol = p; *eol && *eol != '\n'; eol++)
; /* do nothing */
if (!prefixcmp(p, "author ")) {
char *line, *pend, *email, *timestamp;
p += 7;
line = xmalloc(eol + 1 - p);
memcpy(line, p, eol - p);
line[eol - p] = '\0';
email = strchr(line, '<');
if (!email)
die ("Could not extract author email from %s",
sha1_to_hex(commit->object.sha1));
if (email == line)
pend = line;
else
for (pend = email; pend != line + 1 &&
isspace(pend[-1]); pend--);
; /* do nothing */
*pend = '\0';
email++;
timestamp = strchr(email, '>');
if (!timestamp)
die ("Could not extract author email from %s",
sha1_to_hex(commit->object.sha1));
*timestamp = '\0';
for (timestamp++; *timestamp && isspace(*timestamp);
timestamp++)
; /* do nothing */
setenv("GIT_AUTHOR_NAME", line, 1);
setenv("GIT_AUTHOR_EMAIL", email, 1);
setenv("GIT_AUTHOR_DATE", timestamp, 1);
free(line);
return;
}
p = eol;
if (*p == '\n')
p++;
}
die ("No author information found in %s",
sha1_to_hex(commit->object.sha1));
}
static int merge_recursive(const char *base_sha1,
const char *head_sha1, const char *head_name,
const char *next_sha1, const char *next_name)
{
char buffer[256];
const char *argv[6];
sprintf(buffer, "GITHEAD_%s", head_sha1);
setenv(buffer, head_name, 1);
sprintf(buffer, "GITHEAD_%s", next_sha1);
setenv(buffer, next_name, 1);
/*
* This three way merge is an interesting one. We are at
* $head, and would want to apply the change between $commit
* and $prev on top of us (when reverting), or the change between
* $prev and $commit on top of us (when cherry-picking or replaying).
*/
argv[0] = "merge-recursive";
argv[1] = base_sha1;
argv[2] = "--";
argv[3] = head_sha1;
argv[4] = next_sha1;
argv[5] = NULL;
return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);
}
static int revert_or_cherry_pick(int argc, const char **argv)
{
unsigned char head[20];
struct commit *base, *next;
int i;
char *oneline, *reencoded_message = NULL;
const char *message, *encoding;
git_config(git_default_config);
me = action == REVERT ? "revert" : "cherry-pick";
setenv(GIT_REFLOG_ACTION, me, 0);
parse_options(argc, argv);
/* this is copied from the shell script, but it's never triggered... */
if (action == REVERT && replay)
die("revert is incompatible with replay");
if (no_commit) {
/*
* We do not intend to commit immediately. We just want to
* merge the differences in.
*/
if (write_tree(head, 0, NULL))
die ("Your index file is unmerged.");
} else {
struct wt_status s;
if (get_sha1("HEAD", head))
die ("You do not have a valid HEAD");
wt_status_prepare(&s);
if (s.commitable || s.workdir_dirty)
die ("Dirty index: cannot %s", me);
discard_cache();
}
if (!commit->parents)
die ("Cannot %s a root commit", me);
if (commit->parents->next)
die ("Cannot %s a multi-parent commit.", me);
if (!(message = commit->buffer))
die ("Cannot get commit message for %s",
sha1_to_hex(commit->object.sha1));
/*
* "commit" is an existing commit. We would want to apply
* the difference it introduces since its first parent "prev"
* on top of the current HEAD if we are cherry-pick. Or the
* reverse of it if we are revert.
*/
msg_fd = hold_lock_file_for_update(&msg_file, ".msg", 1);
encoding = get_encoding(message);
if (!encoding)
encoding = "utf-8";
if (!git_commit_encoding)
git_commit_encoding = "utf-8";
if ((reencoded_message = reencode_string(message,
git_commit_encoding, encoding)))
message = reencoded_message;
oneline = get_oneline(message);
if (action == REVERT) {
char *oneline_body = strchr(oneline, ' ');
base = commit;
next = commit->parents->item;
add_to_msg("Revert \"");
add_to_msg(oneline_body + 1);
add_to_msg("\"\n\nThis reverts commit ");
add_to_msg(sha1_to_hex(commit->object.sha1));
add_to_msg(".\n");
} else {
base = commit->parents->item;
next = commit;
set_author_ident_env(message);
add_message_to_msg(message);
if (!replay) {
add_to_msg("(cherry picked from commit ");
add_to_msg(sha1_to_hex(commit->object.sha1));
add_to_msg(")\n");
}
}
if (needed_deref) {
add_to_msg("(original 'git ");
add_to_msg(me);
add_to_msg("' arguments: ");
for (i = 0; i < argc; i++) {
if (i)
add_to_msg(" ");
add_to_msg(argv[i]);
}
add_to_msg(")\n");
}
if (merge_recursive(sha1_to_hex(base->object.sha1),
sha1_to_hex(head), "HEAD",
sha1_to_hex(next->object.sha1), oneline) ||
write_tree(head, 0, NULL)) {
const char *target = git_path("MERGE_MSG");
add_to_msg("\nConflicts:\n\n");
read_cache();
for (i = 0; i < active_nr;) {
struct cache_entry *ce = active_cache[i++];
if (ce_stage(ce)) {
add_to_msg("\t");
add_to_msg(ce->name);
add_to_msg("\n");
while (i < active_nr && !strcmp(ce->name,
active_cache[i]->name))
i++;
}
}
if (close(msg_fd) || commit_lock_file(&msg_file) < 0)
die ("Error wrapping up .msg");
unlink(target);
if (rename(".msg", target))
die ("Could not move .msg to %s", target);
fprintf(stderr, "Automatic %s failed. "
"After resolving the conflicts,\n"
"mark the corrected paths with 'git-add <paths>'\n"
"and commit the result.\n", me);
if (action == CHERRY_PICK) {
fprintf(stderr, "When commiting, use the option "
"'-c %s' to retain authorship and message.\n",
find_unique_abbrev(commit->object.sha1,
DEFAULT_ABBREV));
}
exit(1);
}
if (close(msg_fd) || commit_lock_file(&msg_file) < 0)
die ("Error wrapping up .msg");
fprintf(stderr, "Finished one %s.\n", me);
/*
*
* If we are cherry-pick, and if the merge did not result in
* hand-editing, we will hit this commit and inherit the original
* author date and name.
* If we are revert, or if our cherry-pick results in a hand merge,
* we had better say that the current user is responsible for that.
*/
if (!no_commit) {
if (edit)
return execl_git_cmd("commit", "-n", "-F", ".msg",
"-e", NULL);
else
return execl_git_cmd("commit", "-n", "-F", ".msg",
NULL);
}
if (reencoded_message)
free(reencoded_message);
return 0;
}
int cmd_revert(int argc, const char **argv, const char *prefix)
{
if (isatty(0))
edit = 1;
action = REVERT;
return revert_or_cherry_pick(argc, argv);
}
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
{
replay = 1;
action = CHERRY_PICK;
return revert_or_cherry_pick(argc, argv);
}

View File

@ -89,20 +89,10 @@ static int check_local_mod(unsigned char *head)
if (ce_match_stat(ce, &st, 0))
errs = error("'%s' has local modifications "
"(hint: try -f)", ce->name);
if (no_head)
continue;
/*
* It is Ok to remove a newly added path, as long as
* it is cache-clean.
*/
if (get_tree_entry(head, name, sha1, &mode))
continue;
/*
* Otherwise make sure the version from the HEAD
* matches the index.
*/
if (ce->ce_mode != create_ce_mode(mode) ||
hashcmp(ce->sha1, sha1))
if (no_head
|| get_tree_entry(head, name, sha1, &mode)
|| ce->ce_mode != create_ce_mode(mode)
|| hashcmp(ce->sha1, sha1))
errs = error("'%s' has changes staged in the index "
"(hint: try -f)", name);
}

View File

@ -124,7 +124,7 @@ static void insert_author_oneline(struct path_list *list,
else
free(buffer);
if (!strncmp(oneline, "[PATCH", 6)) {
if (!prefixcmp(oneline, "[PATCH")) {
char *eob = strchr(oneline, ']');
if (eob) {
@ -179,7 +179,7 @@ static void read_from_stdin(struct path_list *list)
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
char *bob;
if ((buffer[0] == 'A' || buffer[0] == 'a') &&
!strncmp(buffer + 1, "uthor: ", 7) &&
!prefixcmp(buffer + 1, "uthor: ") &&
(bob = strchr(buffer + 7, '<')) != NULL) {
char buffer2[1024], offset = 0;
@ -217,20 +217,20 @@ static void get_from_rev(struct rev_info *rev, struct path_list *list)
prepare_revision_walk(rev);
while ((commit = get_revision(rev)) != NULL) {
char *author = NULL, *oneline, *buffer;
const char *author = NULL, *oneline, *buffer;
int authorlen = authorlen, onelinelen;
/* get author and oneline */
for (buffer = commit->buffer; buffer && *buffer != '\0' &&
*buffer != '\n'; ) {
char *eol = strchr(buffer, '\n');
const char *eol = strchr(buffer, '\n');
if (eol == NULL)
eol = buffer + strlen(buffer);
else
eol++;
if (!strncmp(buffer, "author ", 7)) {
if (!prefixcmp(buffer, "author ")) {
char *bracket = strchr(buffer, '<');
if (bracket == NULL || bracket > eol)
@ -304,8 +304,11 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
if (!access(".mailmap", R_OK))
read_mailmap(".mailmap");
if (rev.pending.nr == 0)
if (rev.pending.nr == 0) {
if (isatty(0))
fprintf(stderr, "(reading log to summarize from standard input)\n");
read_from_stdin(&list);
}
else
get_from_rev(&rev, &list);

View File

@ -266,7 +266,7 @@ static void show_one_commit(struct commit *commit, int no_name)
pretty, sizeof(pretty), 0, NULL, NULL, 0);
else
strcpy(pretty, "(unavailable)");
if (!strncmp(pretty, "[PATCH] ", 8))
if (!prefixcmp(pretty, "[PATCH] "))
cp = pretty + 8;
else
cp = pretty;
@ -378,7 +378,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1, int f
{
unsigned char tmp[20];
int ofs = 11;
if (strncmp(refname, "refs/heads/", ofs))
if (prefixcmp(refname, "refs/heads/"))
return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
@ -392,7 +392,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
{
unsigned char tmp[20];
int ofs = 13;
if (strncmp(refname, "refs/remotes/", ofs))
if (prefixcmp(refname, "refs/remotes/"))
return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
@ -404,7 +404,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
if (strncmp(refname, "refs/tags/", 10))
if (prefixcmp(refname, "refs/tags/"))
return 0;
return append_ref(refname + 5, sha1, 0);
}
@ -435,9 +435,9 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i
return 0;
if (fnmatch(match_ref_pattern, tail, 0))
return 0;
if (!strncmp("refs/heads/", refname, 11))
if (!prefixcmp(refname, "refs/heads/"))
return append_head_ref(refname, sha1, flag, cb_data);
if (!strncmp("refs/tags/", refname, 10))
if (!prefixcmp(refname, "refs/tags/"))
return append_tag_ref(refname, sha1, flag, cb_data);
return append_ref(refname, sha1, 0);
}
@ -462,11 +462,11 @@ static int rev_is_head(char *head, int headlen, char *name,
if ((!head[0]) ||
(head_sha1 && sha1 && hashcmp(head_sha1, sha1)))
return 0;
if (!strncmp(head, "refs/heads/", 11))
if (!prefixcmp(head, "refs/heads/"))
head += 11;
if (!strncmp(name, "refs/heads/", 11))
if (!prefixcmp(name, "refs/heads/"))
name += 11;
else if (!strncmp(name, "heads/", 6))
else if (!prefixcmp(name, "heads/"))
name += 6;
return !strcmp(head, name);
}
@ -635,7 +635,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
with_current_branch = 1;
else if (!strcmp(arg, "--sha1-name"))
sha1_name = 1;
else if (!strncmp(arg, "--more=", 7))
else if (!prefixcmp(arg, "--more="))
extra = atoi(arg + 7);
else if (!strcmp(arg, "--merge-base"))
merge_base = 1;
@ -652,9 +652,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
reflog = DEFAULT_REFLOG;
}
else if (!strncmp(arg, "--reflog=", 9))
else if (!prefixcmp(arg, "--reflog="))
parse_reflog_param(arg + 9, &reflog, &reflog_base);
else if (!strncmp(arg, "-g=", 3))
else if (!prefixcmp(arg, "-g="))
parse_reflog_param(arg + 3, &reflog, &reflog_base);
else
usage(show_branch_usage);
@ -721,7 +721,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
}
for (i = 0; i < reflog; i++) {
char *logmsg, *msg, *m;
char *logmsg, *m;
const char *msg;
unsigned long timestamp;
int tz;

View File

@ -28,8 +28,8 @@ static int show_ref(const char *refname, const unsigned char *sha1, int flag, vo
if (tags_only || heads_only) {
int match;
match = heads_only && !strncmp(refname, "refs/heads/", 11);
match |= tags_only && !strncmp(refname, "refs/tags/", 10);
match = heads_only && !prefixcmp(refname, "refs/heads/");
match |= tags_only && !prefixcmp(refname, "refs/tags/");
if (!match)
return 0;
}
@ -178,8 +178,8 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
hash_only = 1;
continue;
}
if (!strncmp(arg, "--hash=", 7) ||
(!strncmp(arg, "--abbrev", 8) &&
if (!prefixcmp(arg, "--hash=") ||
(!prefixcmp(arg, "--abbrev") &&
(arg[8] == '=' || arg[8] == '\0'))) {
if (arg[2] != 'h' && !arg[8])
/* --abbrev only */
@ -215,7 +215,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
}
if (!strcmp(arg, "--exclude-existing"))
return exclude_existing(NULL);
if (!strncmp(arg, "--exclude-existing=", 19))
if (!prefixcmp(arg, "--exclude-existing="))
return exclude_existing(arg + 19);
usage(show_ref_usage);
}
@ -226,7 +226,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
while (*pattern) {
unsigned char sha1[20];
if (!strncmp(*pattern, "refs/", 5) &&
if (!prefixcmp(*pattern, "refs/") &&
resolve_ref(*pattern, sha1, 1, NULL)) {
if (!quiet)
show_one(*pattern, sha1);

View File

@ -31,7 +31,7 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)
nargv[nargc++] = "git-archive";
nargv[nargc++] = "--format=tar";
if (2 <= argc && !strncmp("--remote=", argv[1], 9)) {
if (2 <= argc && !prefixcmp(argv[1], "--remote=")) {
nargv[nargc++] = argv[1];
argv++;
argc--;

View File

@ -119,18 +119,18 @@ struct obj_info {
static struct obj_info *obj_list;
static void added_object(unsigned nr, const char *type, void *data,
unsigned long size);
static void added_object(unsigned nr, enum object_type type,
void *data, unsigned long size);
static void write_object(unsigned nr, void *buf, unsigned long size,
const char *type)
static void write_object(unsigned nr, enum object_type type,
void *buf, unsigned long size)
{
if (write_sha1_file(buf, size, type, obj_list[nr].sha1) < 0)
if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
die("failed to write object");
added_object(nr, type, buf, size);
}
static void resolve_delta(unsigned nr, const char *type,
static void resolve_delta(unsigned nr, enum object_type type,
void *base, unsigned long base_size,
void *delta, unsigned long delta_size)
{
@ -143,12 +143,12 @@ static void resolve_delta(unsigned nr, const char *type,
if (!result)
die("failed to apply delta");
free(delta);
write_object(nr, result, result_size, type);
write_object(nr, type, result, result_size);
free(result);
}
static void added_object(unsigned nr, const char *type, void *data,
unsigned long size)
static void added_object(unsigned nr, enum object_type type,
void *data, unsigned long size)
{
struct delta_info **p = &delta_list;
struct delta_info *info;
@ -167,33 +167,24 @@ static void added_object(unsigned nr, const char *type, void *data,
}
}
static void unpack_non_delta_entry(enum object_type kind, unsigned long size,
static void unpack_non_delta_entry(enum object_type type, unsigned long size,
unsigned nr)
{
void *buf = get_data(size);
const char *type;
switch (kind) {
case OBJ_COMMIT: type = commit_type; break;
case OBJ_TREE: type = tree_type; break;
case OBJ_BLOB: type = blob_type; break;
case OBJ_TAG: type = tag_type; break;
default: die("bad type %d", kind);
}
if (!dry_run && buf)
write_object(nr, buf, size, type);
write_object(nr, type, buf, size);
free(buf);
}
static void unpack_delta_entry(enum object_type kind, unsigned long delta_size,
static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
unsigned nr)
{
void *delta_data, *base;
unsigned long base_size;
char type[20];
unsigned char base_sha1[20];
if (kind == OBJ_REF_DELTA) {
if (type == OBJ_REF_DELTA) {
hashcpy(base_sha1, fill(20));
use(20);
delta_data = get_data(delta_size);
@ -255,7 +246,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size,
}
}
base = read_sha1_file(base_sha1, type, &base_size);
base = read_sha1_file(base_sha1, &type, &base_size);
if (!base) {
error("failed to read delta-pack base object %s",
sha1_to_hex(base_sha1));
@ -369,7 +360,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
recover = 1;
continue;
}
if (!strncmp(arg, "--pack_header=", 14)) {
if (!prefixcmp(arg, "--pack_header=")) {
struct pack_header *hdr;
char *c;

View File

@ -109,11 +109,11 @@ static int add_file_to_cache(const char *path)
ce->ce_flags = htons(namelen);
fill_stat_cache_info(ce, &st);
if (trust_executable_bit)
if (trust_executable_bit && has_symlinks)
ce->ce_mode = create_ce_mode(st.st_mode);
else {
/* If there is an existing entry, pick the mode bits
* from it, otherwise assume unexecutable.
/* If there is an existing entry, pick the mode bits and type
* from it, otherwise assume unexecutable regular file.
*/
struct cache_entry *ent;
int pos = cache_name_pos(path, namelen);
@ -487,6 +487,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
int prefix_length = prefix ? strlen(prefix) : 0;
char set_executable_bit = 0;
unsigned int refresh_flags = 0;
int lock_error = 0;
struct lock_file *lock_file;
git_config(git_default_config);
@ -494,7 +495,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
/* We can't free this memory, it becomes part of a linked list parsed atexit() */
lock_file = xcalloc(1, sizeof(struct lock_file));
newfd = hold_lock_file_for_update(lock_file, get_index_file(), 1);
newfd = hold_lock_file_for_update(lock_file, get_index_file(), 0);
if (newfd < 0)
lock_error = errno;
entries = read_cache();
if (entries < 0)
@ -651,6 +654,12 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
finish:
if (active_cache_changed) {
if (newfd < 0) {
if (refresh_flags & REFRESH_QUIET)
exit(128);
die("unable to create '%s.lock': %s",
get_index_file(), strerror(lock_error));
}
if (write_cache(newfd, active_cache, active_nr) ||
close(newfd) || commit_lock_file(lock_file))
die("Unable to write new index file");

View File

@ -70,7 +70,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
const char *arg = argv[1];
if (!strcmp(arg, "--missing-ok"))
missing_ok = 1;
else if (!strncmp(arg, "--prefix=", 9))
else if (!prefixcmp(arg, "--prefix="))
prefix = arg + 9;
else
usage(write_tree_usage);

View File

@ -19,22 +19,25 @@ extern int cmd_apply(int argc, const char **argv, const char *prefix);
extern int cmd_archive(int argc, const char **argv, const char *prefix);
extern int cmd_blame(int argc, const char **argv, const char *prefix);
extern int cmd_branch(int argc, const char **argv, const char *prefix);
extern int cmd_bundle(int argc, const char **argv, const char *prefix);
extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
extern int cmd_cherry(int argc, const char **argv, const char *prefix);
extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
extern int cmd_describe(int argc, const char **argv, const char *prefix);
extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
extern int cmd_diff(int argc, const char **argv, const char *prefix);
extern int cmd_diff_stages(int argc, const char **argv, const char *prefix);
extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix);
extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
extern int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
extern int cmd_fsck(int argc, const char **argv, const char *prefix);
extern int cmd_gc(int argc, const char **argv, const char *prefix);
extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
extern int cmd_grep(int argc, const char **argv, const char *prefix);
extern int cmd_help(int argc, const char **argv, const char *prefix);
@ -45,6 +48,7 @@ extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix);
extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
@ -59,6 +63,7 @@ extern int cmd_config(int argc, const char **argv, const char *prefix);
extern int cmd_rerere(int argc, const char **argv, const char *prefix);
extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
extern int cmd_revert(int argc, const char **argv, const char *prefix);
extern int cmd_rm(int argc, const char **argv, const char *prefix);
extern int cmd_runstatus(int argc, const char **argv, const char *prefix);
extern int cmd_shortlog(int argc, const char **argv, const char *prefix);

78
cache.h
View File

@ -108,7 +108,10 @@ static inline unsigned int create_ce_mode(unsigned int mode)
}
static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
{
extern int trust_executable_bit;
extern int trust_executable_bit, has_symlinks;
if (!has_symlinks && S_ISREG(mode) &&
ce && S_ISLNK(ntohl(ce->ce_mode)))
return ce->ce_mode;
if (!trust_executable_bit && S_ISREG(mode)) {
if (ce && S_ISREG(ntohl(ce->ce_mode)))
return ce->ce_mode;
@ -127,6 +130,19 @@ extern unsigned int active_nr, active_alloc, active_cache_changed;
extern struct cache_tree *active_cache_tree;
extern int cache_errno;
enum object_type {
OBJ_BAD = -1,
OBJ_NONE = 0,
OBJ_COMMIT = 1,
OBJ_TREE = 2,
OBJ_BLOB = 3,
OBJ_TAG = 4,
/* 5 for future expansion */
OBJ_OFS_DELTA = 6,
OBJ_REF_DELTA = 7,
OBJ_MAX,
};
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
@ -177,7 +193,7 @@ extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int);
extern int ce_modified(struct cache_entry *ce, struct stat *st, int);
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type);
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
extern int read_pipe(int fd, char** return_buf, unsigned long* return_size);
extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
@ -202,6 +218,7 @@ extern int delete_ref(const char *, unsigned char *sha1);
/* Environment bits from configuration mechanism */
extern int use_legacy_headers;
extern int trust_executable_bit;
extern int has_symlinks;
extern int assume_unchanged;
extern int prefer_symlink_refs;
extern int log_all_ref_updates;
@ -211,6 +228,8 @@ extern const char *apply_default_whitespace;
extern int zlib_compression_level;
extern size_t packed_git_window_size;
extern size_t packed_git_limit;
extern size_t delta_base_cache_limit;
extern int auto_crlf;
#define GIT_REPO_VERSION 0
extern int repository_format_version;
@ -262,12 +281,11 @@ int safe_create_leading_directories(char *path);
char *enter_repo(char *path, int strict);
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
extern int sha1_object_info(const unsigned char *, char *, unsigned long *);
extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);
extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1);
extern int sha1_object_info(const unsigned char *, unsigned long *);
extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size);
extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
extern int pretend_sha1_file(void *, unsigned long, const char *, unsigned char *);
extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
@ -284,18 +302,6 @@ extern int legacy_loose_object(unsigned char *);
extern int has_pack_file(const unsigned char *sha1);
extern int has_pack_index(const unsigned char *sha1);
enum object_type {
OBJ_NONE = 0,
OBJ_COMMIT = 1,
OBJ_TREE = 2,
OBJ_BLOB = 3,
OBJ_TAG = 4,
/* 5 for future expansion */
OBJ_OFS_DELTA = 6,
OBJ_REF_DELTA = 7,
OBJ_BAD,
};
extern signed char hexval_table[256];
static inline unsigned int hexval(unsigned int c)
{
@ -325,7 +331,8 @@ extern void *read_object_with_reference(const unsigned char *sha1,
unsigned long *size,
unsigned char *sha1_ret);
const char *show_date(unsigned long time, int timezone, int relative);
enum date_mode { DATE_NORMAL = 0, DATE_RELATIVE, DATE_SHORT };
const char *show_date(unsigned long time, int timezone, enum date_mode mode);
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);
@ -365,9 +372,11 @@ struct pack_window {
extern struct packed_git {
struct packed_git *next;
struct pack_window *windows;
uint32_t *index_base;
const void *index_data;
off_t index_size;
off_t pack_size;
time_t mtime;
int index_version;
int pack_fd;
int pack_local;
unsigned char sha1[20];
@ -376,7 +385,7 @@ extern struct packed_git {
} *packed_git;
struct pack_entry {
unsigned int offset;
off_t offset;
unsigned char sha1[20];
struct packed_git *p;
};
@ -405,7 +414,7 @@ extern int server_supports(const char *feature);
extern struct packed_git *parse_pack_index(unsigned char *sha1);
extern struct packed_git *parse_pack_index_file(const unsigned char *sha1,
char *idx_path);
const char *idx_path);
extern void prepare_packed_git(void);
extern void reprepare_packed_git(void);
@ -415,15 +424,15 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1,
struct packed_git *packs);
extern void pack_report(void);
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, unsigned long, unsigned int *);
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
extern void unuse_pack(struct pack_window **);
extern struct packed_git *add_packed_git(char *, int, int);
extern int num_packed_objects(const struct packed_git *p);
extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*);
extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *);
extern void *unpack_entry(struct packed_git *, unsigned long, char *, unsigned long *);
extern struct packed_git *add_packed_git(const char *, int, int);
extern uint32_t num_packed_objects(const struct packed_git *p);
extern int nth_packed_object_sha1(const struct packed_git *, uint32_t, unsigned char*);
extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
extern void packed_object_info_detail(struct packed_git *, unsigned long, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
/* Dumb servers support */
extern int update_server_info(int);
@ -443,8 +452,8 @@ extern int check_repository_format_version(const char *var, const char *value);
extern char git_default_email[MAX_GITNAME];
extern char git_default_name[MAX_GITNAME];
extern char *git_commit_encoding;
extern char *git_log_output_encoding;
extern const char *git_commit_encoding;
extern const char *git_log_output_encoding;
extern int copy_fd(int ifd, int ofd);
extern int read_in_full(int fd, void *buf, size_t count);
@ -474,8 +483,13 @@ extern struct tag *alloc_tag_node(void);
extern void alloc_report(void);
/* trace.c */
extern int nfasprintf(char **str, const char *fmt, ...);
extern int nfvasprintf(char **str, const char *fmt, va_list va);
extern void trace_printf(const char *format, ...);
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
/* convert.c */
extern int convert_to_git(const char *path, char **bufp, unsigned long *sizep);
extern int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep);
#endif /* CACHE_H */

View File

@ -92,14 +92,14 @@ struct sline {
static char *grab_blob(const unsigned char *sha1, unsigned long *size)
{
char *blob;
char type[20];
enum object_type type;
if (is_null_sha1(sha1)) {
/* deleted blob */
*size = 0;
return xcalloc(1, 1);
}
blob = read_sha1_file(sha1, type, size);
if (strcmp(type, blob_type))
blob = read_sha1_file(sha1, &type, size);
if (type != OBJ_BLOB)
die("object '%s' is not a blob!", sha1_to_hex(sha1));
return blob;
}
@ -684,7 +684,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
goto deleted_file;
if (S_ISLNK(st.st_mode)) {
size_t len = st.st_size;
size_t len = xsize_t(st.st_size);
result_size = len;
result = xmalloc(len + 1);
if (result_size != readlink(elem->path, result, len)) {
@ -697,10 +697,20 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
}
else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
!fstat(fd, &st)) {
size_t len = st.st_size;
size_t len = xsize_t(st.st_size);
size_t sz = 0;
int is_file, i;
elem->mode = canon_mode(st.st_mode);
/* if symlinks don't work, assume symlink if all parents
* are symlinks
*/
is_file = has_symlinks;
for (i = 0; !is_file && i < num_parent; i++)
is_file = !S_ISLNK(elem->parent[i].mode);
if (!is_file)
elem->mode = canon_mode(S_IFLNK);
result_size = len;
result = xmalloc(len + 1);
while (sz < len) {

Some files were not shown because too many files have changed in this diff Show More