mirror of
https://github.com/git/git.git
synced 2026-03-13 10:23:30 +01:00
Merge commit 'junio/master' into devel
Conflicts: Makefile builtin-clone.c t/t4109-apply-multifrag.sh t/t4110-apply-scan.sh
This commit is contained in:
9
.mailmap
9
.mailmap
@@ -5,22 +5,28 @@
|
||||
# same person appearing not to be so.
|
||||
#
|
||||
|
||||
Alexander Gavrilov <angavrilov@gmail.com>
|
||||
Aneesh Kumar K.V <aneesh.kumar@gmail.com>
|
||||
Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
|
||||
Chris Shoemaker <c.shoemaker@cox.net>
|
||||
Dana L. How <danahow@gmail.com>
|
||||
Dana L. How <how@deathvalley.cswitch.com>
|
||||
Daniel Barkalow <barkalow@iabervon.org>
|
||||
David D. Kilzer <ddkilzer@kilzer.net>
|
||||
David Kågedal <davidk@lysator.liu.se>
|
||||
David S. Miller <davem@davemloft.net>
|
||||
Dirk Süsserott <newsletter@dirk.my1.cc>
|
||||
Fredrik Kuivinen <freku045@student.liu.se>
|
||||
H. Peter Anvin <hpa@bonde.sc.orionmulti.com>
|
||||
H. Peter Anvin <hpa@tazenda.sc.orionmulti.com>
|
||||
H. Peter Anvin <hpa@trantor.hos.anvin.org>
|
||||
Horst H. von Brand <vonbrand@inf.utfsm.cl>
|
||||
İsmail Dönmez <ismail@pardus.org.tr>
|
||||
Jay Soffian <jaysoffian+git@gmail.com>
|
||||
Joachim Berdal Haga <cjhaga@fys.uio.no>
|
||||
Jon Loeliger <jdl@freescale.com>
|
||||
Jon Seymour <jon@blackcubes.dyndns.org>
|
||||
Jonathan Nieder <jrnieder@uchicago.edu>
|
||||
Junio C Hamano <junio@twinsun.com>
|
||||
Karl Hasselström <kha@treskal.com>
|
||||
Kent Engstrom <kent@lysator.liu.se>
|
||||
@@ -30,9 +36,12 @@ Li Hong <leehong@pku.edu.cn>
|
||||
Lukas Sandström <lukass@etek.chalmers.se>
|
||||
Martin Langhoff <martin@catalyst.net.nz>
|
||||
Michael Coleman <tutufan@gmail.com>
|
||||
Michael W. Olson <mwolson@gnu.org>
|
||||
Michele Ballabio <barra_cuda@katamail.com>
|
||||
Nanako Shiraishi <nanako3@bluebottle.com>
|
||||
Nanako Shiraishi <nanako3@lavabit.com>
|
||||
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
|
||||
Philippe Bruhat <book@cpan.org>
|
||||
Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
|
||||
René Scharfe <rene.scharfe@lsrfire.ath.cx>
|
||||
Robert Fitzsimons <robfitz@273k.net>
|
||||
|
||||
@@ -105,7 +105,7 @@ For C programs:
|
||||
|
||||
- Use the API. No, really. We have a strbuf (variable length
|
||||
string), several arrays with the ALLOC_GROW() macro, a
|
||||
path_list for sorted string lists, a hash map (mapping struct
|
||||
string_list for sorted string lists, a hash map (mapping struct
|
||||
objects) named "struct decorate", amongst other things.
|
||||
|
||||
- When you come up with an API, document it.
|
||||
|
||||
47
Documentation/RelNotes-1.5.6.4.txt
Normal file
47
Documentation/RelNotes-1.5.6.4.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
GIT v1.5.6.4 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.5.6.3
|
||||
--------------------
|
||||
|
||||
* Various commands could overflow its internal buffer on a platform
|
||||
with small PATH_MAX value in a repository that has contents with
|
||||
long pathnames.
|
||||
|
||||
* There wasn't a way to make --pretty=format:%<> specifiers to honor
|
||||
.mailmap name rewriting for authors and committers. Now you can with
|
||||
%aN and %cN.
|
||||
|
||||
* Bash completion wasted too many cycles; this has been optimized to be
|
||||
usable again.
|
||||
|
||||
* Bash completion lost ref part when completing something like "git show
|
||||
pu:Makefile".
|
||||
|
||||
* "git-cvsserver" did not clean up its temporary working area after annotate
|
||||
request.
|
||||
|
||||
* "git-daemon" called syslog() from its signal handler, which was a
|
||||
no-no.
|
||||
|
||||
* "git-fetch" into an empty repository used to remind that the fetch will
|
||||
be huge by saying "no common commits", but this was an unnecessary
|
||||
noise; it is already known by the user anyway.
|
||||
|
||||
* "git-http-fetch" would have segfaulted when pack idx file retrieved
|
||||
from the other side was corrupt.
|
||||
|
||||
* "git-index-pack" used too much memory when dealing with a deep delta chain.
|
||||
|
||||
* "git-mailinfo" (hence "git-am") did not correctly handle in-body [PATCH]
|
||||
line to override the commit title taken from the mail Subject header.
|
||||
|
||||
* "git-rebase -i -p" lost parents that are not involved in the history
|
||||
being rewritten.
|
||||
|
||||
* "git-rm" lost track of where the index file was when GIT_DIR was
|
||||
specified as a relative path.
|
||||
|
||||
* "git-rev-list --quiet" was not quiet as advertised.
|
||||
|
||||
Contains other various documentation fixes.
|
||||
@@ -21,13 +21,19 @@ main git.git codebase.
|
||||
By default, packfiles created with this version uses delta-base-offset
|
||||
encoding introduced in v1.4.4. Pack idx files are using version 2 that
|
||||
allows larger packs and added robustness thanks to its CRC checking,
|
||||
introduced in v1.5.2.
|
||||
introduced in v1.5.2 and v1.4.4.5. If you want to keep your repositories
|
||||
backwards compatible past these versions, set repack.useDeltaBaseOffset
|
||||
to false or pack.indexVersion to 1, respectively.
|
||||
|
||||
GIT_CONFIG, which was only documented as affecting "git config", but
|
||||
actually affected all git commands, now only affects "git config".
|
||||
GIT_LOCAL_CONFIG, also only documented as affecting "git config" and
|
||||
not different from GIT_CONFIG in a useful way, is removed.
|
||||
|
||||
The ".dotest" temporary area "git am" and "git rebase" use is now moved
|
||||
inside the $GIT_DIR, to avoid mistakes of adding it to the project by
|
||||
accident.
|
||||
|
||||
An ancient merge strategy "stupid" has been removed.
|
||||
|
||||
|
||||
@@ -67,7 +73,8 @@ Updates since v1.5.6
|
||||
|
||||
(performance, robustness, sanity etc.)
|
||||
|
||||
* even more documentation pages are now accessible via "man" and "git help".
|
||||
* index-pack used too much memory when dealing with a deep delta chain.
|
||||
This has been optimized.
|
||||
|
||||
* reduced excessive inlining to shrink size of the "git" binary.
|
||||
|
||||
@@ -79,6 +86,8 @@ Updates since v1.5.6
|
||||
repack -a -f" can be used to fix such a corruption as long as necessary
|
||||
objects are available.
|
||||
|
||||
* Performance of "git-blame -C -C" operation is vastly improved.
|
||||
|
||||
* git-clone does not create refs in loose form anymore (it behaves as
|
||||
if you immediately ran git-pack-refs after cloning). This will help
|
||||
repositories with insanely large number of refs.
|
||||
@@ -92,6 +101,8 @@ Updates since v1.5.6
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
* even more documentation pages are now accessible via "man" and "git help".
|
||||
|
||||
* A new environment variable GIT_CEILING_DIRECTORIES can be used to stop
|
||||
the discovery process of the toplevel of working tree; this may be useful
|
||||
when you are working in a slow network disk and are outside any working tree,
|
||||
@@ -125,6 +136,9 @@ Updates since v1.5.6
|
||||
* git-archive can be told to omit certain paths from its output using
|
||||
export-ignore attributes.
|
||||
|
||||
* git-archive uses the zlib default compression level when creating
|
||||
zip archive.
|
||||
|
||||
* With -v option, git-branch describes the remote tracking statistics
|
||||
similar to the way git-checkout reports by how many commits your branch
|
||||
is ahead/behind.
|
||||
@@ -144,6 +158,8 @@ Updates since v1.5.6
|
||||
* git-clone can clone from a remote whose URL would be rewritten by
|
||||
configuration stored in $HOME/.gitconfig now.
|
||||
|
||||
* git-cvsserver learned to respond to "cvs co -c".
|
||||
|
||||
* git-diff --check now checks leftover merge conflict markers.
|
||||
|
||||
* When remote side used to have branch 'foo' and git-fetch finds that now
|
||||
@@ -155,6 +171,8 @@ Updates since v1.5.6
|
||||
* fast-export learned to export and import marks file; this can be used to
|
||||
interface with fast-import incrementally.
|
||||
|
||||
* fast-import and fast-export learned to export and import gitlinks.
|
||||
|
||||
* git-rebase records the original tip of branch in ORIG_HEAD before it is
|
||||
rewound.
|
||||
|
||||
@@ -188,6 +206,8 @@ Updates since v1.5.6
|
||||
|
||||
(internal)
|
||||
|
||||
* git-merge has been reimplemented in C.
|
||||
|
||||
|
||||
Fixes since v1.5.6
|
||||
------------------
|
||||
@@ -195,12 +215,8 @@ Fixes since v1.5.6
|
||||
All of the fixes in v1.5.6 maintenance series are included in
|
||||
this release, unless otherwise noted.
|
||||
|
||||
* "git fetch" into an empty repository used to remind the fetch will
|
||||
be huge by saying "no common commits", but it is already known by
|
||||
the user anyway (need to backport 8cb560f to 'maint').
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.5.6.3-350-g499027b
|
||||
O=v1.5.6.4-432-g6796399
|
||||
echo O=$(git describe refs/heads/master)
|
||||
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
|
||||
|
||||
@@ -301,7 +301,7 @@ If it does not apply correctly, there can be various reasons.
|
||||
patch appropriately.
|
||||
|
||||
* Your MUA corrupted your patch; "am" would complain that
|
||||
the patch does not apply. Look at .git/rebase/ subdirectory and
|
||||
the patch does not apply. Look at .git/rebase-apply/ subdirectory and
|
||||
see what 'patch' file contains and check for the common
|
||||
corruption patterns mentioned above.
|
||||
|
||||
|
||||
@@ -358,7 +358,8 @@ core.whitespace::
|
||||
A comma separated list of common whitespace problems to
|
||||
notice. 'git-diff' will use `color.diff.whitespace` to
|
||||
highlight them, and 'git-apply --whitespace=error' will
|
||||
consider them as errors:
|
||||
consider them as errors. You can prefix `-` to disable
|
||||
any of them (e.g. `-trailing-space`):
|
||||
+
|
||||
* `trailing-space` treats trailing whitespaces at the end of the line
|
||||
as an error (enabled by default).
|
||||
|
||||
@@ -96,7 +96,7 @@ index fabadb8,cc95eb0..4866510
|
||||
+
|
||||
or like this (when '--cc' option is used):
|
||||
|
||||
diff --c file
|
||||
diff --cc file
|
||||
|
||||
2. It is followed by one or more extended header lines
|
||||
(this example shows a merge with two parents):
|
||||
|
||||
@@ -9,7 +9,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
|
||||
[--update | -u] [--refresh] [--ignore-errors] [--]
|
||||
[--all | [--update | -u]] [--refresh] [--ignore-errors] [--]
|
||||
<filepattern>...
|
||||
|
||||
DESCRIPTION
|
||||
@@ -86,6 +86,12 @@ OPTIONS
|
||||
command line. If no paths are specified, all tracked files in the
|
||||
current directory and its subdirectories are updated.
|
||||
|
||||
-A::
|
||||
--all::
|
||||
Update files that git already knows about (same as '\--update')
|
||||
and add all untracked files that are not ignored by '.gitignore'
|
||||
mechanism.
|
||||
|
||||
--refresh::
|
||||
Don't add the file(s), but only refresh their stat()
|
||||
information in the index.
|
||||
|
||||
@@ -13,7 +13,7 @@ SYNOPSIS
|
||||
[--3way] [--interactive] [--binary]
|
||||
[--whitespace=<option>] [-C<n>] [-p<n>]
|
||||
[<mbox> | <Maildir>...]
|
||||
'git am' (--skip | --resolved)
|
||||
'git am' (--skip | --resolved | --abort)
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -99,6 +99,9 @@ default. You could use `--no-utf8` to override this.
|
||||
or `--skip` to handle the failure. This is solely
|
||||
for internal use between 'git-rebase' and 'git-am'.
|
||||
|
||||
--abort::
|
||||
Restore the original branch and abort the patching operation.
|
||||
|
||||
DISCUSSION
|
||||
----------
|
||||
|
||||
@@ -140,9 +143,9 @@ aborts in the middle,. You can recover from this in one of two ways:
|
||||
the index file to bring it in a state that the patch should
|
||||
have produced. Then run the command with '--resolved' option.
|
||||
|
||||
The command refuses to process new mailboxes while `.git/rebase`
|
||||
The command refuses to process new mailboxes while `.git/rebase-apply`
|
||||
directory exists, so if you decide to start over from scratch,
|
||||
run `rm -f -r .git/rebase` before running the command with mailbox
|
||||
run `rm -f -r .git/rebase-apply` before running the command with mailbox
|
||||
names.
|
||||
|
||||
Before any patches are applied, ORIG_HEAD is set to the tip of the
|
||||
@@ -159,7 +162,7 @@ linkgit:git-apply[1].
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -190,7 +190,7 @@ linkgit:git-annotate[1]
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
GIT
|
||||
---
|
||||
|
||||
@@ -205,7 +205,7 @@ but different purposes:
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and Junio C Hamano <junkio@cox.net>
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -30,7 +30,7 @@ linkgit:gitattributes[5].
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -9,7 +9,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git checkout' [-q] [-f] [[--track | --no-track] -b <new_branch> [-l]] [-m] [<branch>]
|
||||
'git checkout' [<tree-ish>] <paths>...
|
||||
'git checkout' [<tree-ish>] [--] <paths>...
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
@@ -58,14 +58,14 @@ OPTIONS
|
||||
Usually the command automatically creates a commit with
|
||||
a commit log message stating which commit was
|
||||
cherry-picked. This flag applies the change necessary
|
||||
to cherry-pick the named commit to your working tree,
|
||||
but does not make the commit. In addition, when this
|
||||
option is used, your working tree does not have to match
|
||||
to cherry-pick the named commit to your working tree
|
||||
and the index, but does not make the commit. In addition,
|
||||
when this option is used, your index does not have to match
|
||||
the HEAD commit. The cherry-pick is done against the
|
||||
beginning state of your working tree.
|
||||
beginning state of your index.
|
||||
+
|
||||
This is useful when cherry-picking more than one commits'
|
||||
effect to your working tree in a row.
|
||||
effect to your index in a row.
|
||||
|
||||
-s::
|
||||
--signoff::
|
||||
@@ -74,7 +74,7 @@ effect to your working tree in a row.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -64,7 +64,7 @@ linkgit:git-patch-id[1]
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -87,8 +87,8 @@ then the cloned repository will become corrupt.
|
||||
|
||||
--quiet::
|
||||
-q::
|
||||
Operate quietly. This flag is passed to "rsync" and
|
||||
'git-fetch-pack' commands when given.
|
||||
Operate quietly. This flag is also passed to the `rsync'
|
||||
command when given.
|
||||
|
||||
--no-checkout::
|
||||
-n::
|
||||
@@ -113,9 +113,8 @@ then the cloned repository will become corrupt.
|
||||
|
||||
--upload-pack <upload-pack>::
|
||||
-u <upload-pack>::
|
||||
When given, and the repository to clone from is handled
|
||||
by 'git-fetch-pack', `--exec=<upload-pack>` is passed to
|
||||
the command to specify non-default path for the command
|
||||
When given, and the repository to clone from is accessed
|
||||
via ssh, this specifies a non-default path for the command
|
||||
run on the other end.
|
||||
|
||||
--template=<template_directory>::
|
||||
|
||||
@@ -331,7 +331,7 @@ linkgit:git-commit-tree[1]
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||
Junio C Hamano <junkio@cox.net>
|
||||
Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
|
||||
GIT
|
||||
|
||||
@@ -27,7 +27,7 @@ OPTIONS
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -136,7 +136,7 @@ will be the smallest number of commits possible.
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>, but somewhat
|
||||
butchered by Junio C Hamano <junkio@cox.net>. Later significantly
|
||||
butchered by Junio C Hamano <gitster@pobox.com>. Later significantly
|
||||
updated by Shawn Pearce <spearce@spearce.org>.
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -93,11 +93,11 @@ include::pretty-options.txt[]
|
||||
This flag changes the way a merge commit patch is displayed,
|
||||
in a similar way to the '-c' option. It implies the '-c'
|
||||
and '-p' options and further compresses the patch output
|
||||
by omitting hunks that show differences from only one
|
||||
parent, or show the same change from all but one parent
|
||||
for an Octopus merge. When this optimization makes all
|
||||
hunks disappear, the commit itself and the commit log
|
||||
message is not shown, just like in any other "empty diff" case.
|
||||
by omitting uninteresting hunks whose the contents in the parents
|
||||
have only two variants and the merge result picks one of them
|
||||
without modification. When all hunks are uninteresting, the commit
|
||||
itself and the commit log message is not shown, just like in any other
|
||||
"empty diff" case.
|
||||
|
||||
--always::
|
||||
Show the commit itself and the commit log message even
|
||||
|
||||
@@ -481,6 +481,9 @@ in octal. Git only supports the following modes:
|
||||
what you want.
|
||||
* `100755` or `755`: A normal, but executable, file.
|
||||
* `120000`: A symlink, the content of the file will be the link target.
|
||||
* `160000`: A gitlink, SHA-1 of the object refers to a commit in
|
||||
another repository. Git links can only be specified by SHA or through
|
||||
a commit mark. They are used to implement submodules.
|
||||
|
||||
In both formats `<path>` is the complete path of the file to be added
|
||||
(if not already existing) or modified (if already existing).
|
||||
|
||||
@@ -45,7 +45,7 @@ linkgit:git-pull[1]
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||
Junio C Hamano <junkio@cox.net>
|
||||
Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
@@ -191,7 +191,7 @@ Thus you may instead want to use `rm -f filename` as the script.
|
||||
A significantly faster version:
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
git filter-branch --index-filter 'git update-index --remove filename' HEAD
|
||||
git filter-branch --index-filter 'git rm --cached filename' HEAD
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Now, you will get the rewritten history saved in HEAD.
|
||||
|
||||
@@ -61,7 +61,7 @@ linkgit:git-merge[1]
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -235,7 +235,7 @@ linkgit:git-am[1], linkgit:git-send-email[1]
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -37,7 +37,7 @@ OPTIONS
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -69,7 +69,7 @@ EXAMPLES
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
GIT
|
||||
---
|
||||
|
||||
@@ -81,7 +81,7 @@ with minimum width of 7 characters. Object size is given only for blobs
|
||||
Author
|
||||
------
|
||||
Written by Petr Baudis <pasky@suse.cz>
|
||||
Completely rewritten from scratch by Junio C Hamano <junkio@cox.net>,
|
||||
Completely rewritten from scratch by Junio C Hamano <gitster@pobox.com>,
|
||||
another major rewrite by Linus Torvalds <torvalds@osdl.org>
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -60,7 +60,7 @@ conversion, even with this flag.
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||
Junio C Hamano <junkio@cox.net>
|
||||
Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -46,7 +46,7 @@ OPTIONS
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>
|
||||
and Junio C Hamano <junkio@cox.net>
|
||||
and Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -18,7 +18,7 @@ to resolve a merge after the trivial merge done with 'git-read-tree -m'.
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>,
|
||||
Junio C Hamano <junkio@cox.net> and Petr Baudis <pasky@suse.cz>.
|
||||
Junio C Hamano <gitster@pobox.com> and Petr Baudis <pasky@suse.cz>.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -57,50 +57,31 @@ HOW MERGE WORKS
|
||||
|
||||
A merge is always between the current `HEAD` and one or more
|
||||
commits (usually, branch head or tag), and the index file must
|
||||
exactly match the
|
||||
tree of `HEAD` commit (i.e. the contents of the last commit) when
|
||||
it happens. In other words, `git diff --cached HEAD` must
|
||||
report no changes.
|
||||
match the tree of `HEAD` commit (i.e. the contents of the last commit)
|
||||
when it starts out. In other words, `git diff --cached HEAD` must
|
||||
report no changes. (One exception is when the changed index
|
||||
entries are already in the same state that would result from
|
||||
the merge anyway.)
|
||||
|
||||
[NOTE]
|
||||
This is a bit of a lie. In certain special cases, your index is
|
||||
allowed to be different from the tree of the `HEAD` commit. The most
|
||||
notable case is when your `HEAD` commit is already ahead of what
|
||||
is being merged, in which case your index can have arbitrary
|
||||
differences from your `HEAD` commit. Also, your index entries
|
||||
may have differences from your `HEAD` commit that match
|
||||
the result of a trivial merge (e.g. you received the same patch
|
||||
from an external source to produce the same result as what you are
|
||||
merging). For example, if a path did not exist in the common
|
||||
ancestor and your head commit but exists in the tree you are
|
||||
merging into your repository, and if you already happen to have
|
||||
that path exactly in your index, the merge does not have to
|
||||
fail.
|
||||
Three kinds of merge can happen:
|
||||
|
||||
Otherwise, merge will refuse to do any harm to your repository
|
||||
(that is, it may fetch the objects from remote, and it may even
|
||||
update the local branch used to keep track of the remote branch
|
||||
with `git pull remote rbranch:lbranch`, but your working tree,
|
||||
`.git/HEAD` pointer and index file are left intact). In addition,
|
||||
merge always sets `.git/ORIG_HEAD` to the original state of HEAD so
|
||||
a problematic merge can be removed by using `git reset ORIG_HEAD`.
|
||||
* The merged commit is already contained in `HEAD`. This is the
|
||||
simplest case, called "Already up-to-date."
|
||||
|
||||
You may have local modifications in the working tree files. In
|
||||
other words, 'git-diff' is allowed to report changes.
|
||||
However, the merge uses your working tree as the working area,
|
||||
and in order to prevent the merge operation from losing such
|
||||
changes, it makes sure that they do not interfere with the
|
||||
merge. Those complex tables in read-tree documentation define
|
||||
what it means for a path to "interfere with the merge". And if
|
||||
your local modifications interfere with the merge, again, it
|
||||
stops before touching anything.
|
||||
* `HEAD` is already contained in the merged commit. This is the
|
||||
most common case especially when involved through 'git pull':
|
||||
you are tracking an upstream repository, committed no local
|
||||
changes and now you want to update to a newer upstream revision.
|
||||
Your `HEAD` (and the index) is updated to at point the merged
|
||||
commit, without creating an extra merge commit. This is
|
||||
called "Fast-forward".
|
||||
|
||||
So in the above two "failed merge" case, you do not have to
|
||||
worry about loss of data --- you simply were not ready to do
|
||||
a merge, so no merge happened at all. You may want to finish
|
||||
whatever you were in the middle of doing, and retry the same
|
||||
pull after you are done and ready.
|
||||
* Both the merged commit and `HEAD` are independent and must be
|
||||
tied together by a merge commit that has them both as its parents.
|
||||
The rest of this section describes this "True merge" case.
|
||||
|
||||
The chosen merge strategy merges the two commits into a single
|
||||
new source tree.
|
||||
When things cleanly merge, these things happen:
|
||||
|
||||
1. The results are updated both in the index file and in your
|
||||
@@ -142,12 +123,13 @@ After seeing a conflict, you can do two things:
|
||||
|
||||
* Decide not to merge. The only clean-up you need are to reset
|
||||
the index file to the `HEAD` commit to reverse 2. and to clean
|
||||
up working tree changes made by 2. and 3.; 'git-reset' can
|
||||
up working tree changes made by 2. and 3.; 'git-reset --hard' can
|
||||
be used for this.
|
||||
|
||||
* Resolve the conflicts. `git diff` would report only the
|
||||
conflicting paths because of the above 2. and 3. Edit the
|
||||
working tree files into a desirable shape, 'git-add' or 'git-rm'
|
||||
conflicting paths because of the above 2. and 3.
|
||||
Edit the working tree files into a desirable shape
|
||||
('git mergetool' can ease this task), 'git-add' or 'git-rm'
|
||||
them, to make the index file contain what the merge result
|
||||
should be, and run 'git-commit' to commit the result.
|
||||
|
||||
@@ -163,7 +145,7 @@ linkgit:git-mergetool[1]
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -23,7 +23,7 @@ OPTIONS
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -39,7 +39,7 @@ OPTIONS
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -193,7 +193,7 @@ linkgit:git-fetch[1], linkgit:git-merge[1], linkgit:git-config[1]
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>
|
||||
and Junio C Hamano <junkio@cox.net>
|
||||
and Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -195,7 +195,7 @@ git push origin master:refs/heads/experimental::
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>, later rewritten in C
|
||||
Written by Junio C Hamano <gitster@pobox.com>, later rewritten in C
|
||||
by Linus Torvalds <torvalds@osdl.org>
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -39,8 +39,8 @@ It is possible that a merge failure will prevent this process from being
|
||||
completely automatic. You will have to resolve any such merge failure
|
||||
and run `git rebase --continue`. Another option is to bypass the commit
|
||||
that caused the merge failure with `git rebase --skip`. To restore the
|
||||
original <branch> and remove the .git/rebase working files, use the command
|
||||
`git rebase --abort` instead.
|
||||
original <branch> and remove the .git/rebase-apply working files, use the
|
||||
command `git rebase --abort` instead.
|
||||
|
||||
Assume the following history exists and the current branch is "topic":
|
||||
|
||||
@@ -398,7 +398,7 @@ after each commit, test, and amend the commit if fixes are necessary.
|
||||
|
||||
Authors
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net> and
|
||||
Written by Junio C Hamano <gitster@pobox.com> and
|
||||
Johannes E. Schindelin <johannes.schindelin@gmx.de>
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -94,7 +94,7 @@ them.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -28,7 +28,7 @@ OPTIONS
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Ryan Anderson <ryan@michonline.com> and Junio C Hamano <junkio@cox.net>
|
||||
Written by Ryan Anderson <ryan@michonline.com> and Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -37,7 +37,7 @@ its working state.
|
||||
'clear'::
|
||||
|
||||
This resets the metadata used by rerere if a merge resolution is to be
|
||||
is aborted. Calling 'git-am --skip' or 'git-rebase [--skip|--abort]'
|
||||
aborted. Calling 'git-am [--skip|--abort]' or 'git-rebase [--skip|--abort]'
|
||||
will automatically invoke this command.
|
||||
|
||||
'diff'::
|
||||
@@ -204,7 +204,7 @@ conflict.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
GIT
|
||||
---
|
||||
|
||||
@@ -195,7 +195,7 @@ $ git add frotz.c <3>
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net> and Linus Torvalds <torvalds@osdl.org>
|
||||
Written by Junio C Hamano <gitster@pobox.com> and Linus Torvalds <torvalds@osdl.org>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -426,7 +426,7 @@ but if $REV is empty, the commit object name from master will be printed.
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> .
|
||||
Junio C Hamano <junkio@cox.net> and Pierre Habouzit <madcoder@debian.org>
|
||||
Junio C Hamano <gitster@pobox.com> and Pierre Habouzit <madcoder@debian.org>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -43,16 +43,16 @@ OPTIONS
|
||||
-n::
|
||||
--no-commit::
|
||||
Usually the command automatically creates a commit with
|
||||
a commit log message stating which commit was reverted.
|
||||
This flag applies the change necessary to revert the
|
||||
named commit to your working tree, but does not make the
|
||||
commit. In addition, when this option is used, your
|
||||
working tree does not have to match the HEAD commit.
|
||||
The revert is done against the beginning state of your
|
||||
working tree.
|
||||
a commit log message stating which commit was
|
||||
reverted. This flag applies the change necessary
|
||||
to revert the named commit to your working tree
|
||||
and the index, but does not make the commit. In addition,
|
||||
when this option is used, your index does not have to match
|
||||
the HEAD commit. The revert is done against the
|
||||
beginning state of your index.
|
||||
+
|
||||
This is useful when reverting more than one commits'
|
||||
effect to your working tree in a row.
|
||||
effect to your index in a row.
|
||||
|
||||
-s::
|
||||
--signoff::
|
||||
@@ -61,7 +61,7 @@ effect to your working tree in a row.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -182,7 +182,7 @@ topologically related with each other.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -71,7 +71,7 @@ include::i18n.txt[]
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||
Junio C Hamano <junkio@cox.net>. Significantly enhanced by
|
||||
Junio C Hamano <gitster@pobox.com>. Significantly enhanced by
|
||||
Johannes Schindelin <Johannes.Schindelin@gmx.de>.
|
||||
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ linkgit:gitignore[5]
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||
Junio C Hamano <junkio@cox.net>.
|
||||
Junio C Hamano <gitster@pobox.com>.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -16,6 +16,48 @@ SYNOPSIS
|
||||
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Submodules allow foreign repositories to be embedded within
|
||||
a dedicated subdirectory of the source tree, always pointed
|
||||
at a particular commit.
|
||||
|
||||
They are not to be confused with remotes, which are meant mainly
|
||||
for branches of the same project; submodules are meant for
|
||||
different projects you would like to make part of your source tree,
|
||||
while the history of the two projects still stays completely
|
||||
independent and you cannot modify the contents of the submodule
|
||||
from within the main project.
|
||||
If you want to merge the project histories and want to treat the
|
||||
aggregated whole as a single project from then on, you may want to
|
||||
add a remote for the other project and use the 'subtree' merge strategy,
|
||||
instead of treating the other project as a submodule. Directories
|
||||
that come from both projects can be cloned and checked out as a whole
|
||||
if you choose to go that route.
|
||||
|
||||
Submodules are composed from a so-called `gitlink` tree entry
|
||||
in the main repository that refers to a particular commit object
|
||||
within the inner repository that is completely separate.
|
||||
A record in the `.gitmodules` file at the root of the source
|
||||
tree assigns a logical name to the submodule and describes
|
||||
the default URL the submodule shall be cloned from.
|
||||
The logical name can be used for overriding this URL within your
|
||||
local repository configuration (see 'submodule init').
|
||||
|
||||
This command will manage the tree entries and contents of the
|
||||
gitmodules file for you, as well as inspect the status of your
|
||||
submodules and update them.
|
||||
When adding a new submodule to the tree, the 'add' subcommand
|
||||
is to be used. However, when pulling a tree containing submodules,
|
||||
these will not be checked out by default;
|
||||
the 'init' and 'update' subcommands will maintain submodules
|
||||
checked out and at appropriate revision in your working tree.
|
||||
You can briefly inspect the up-to-date status of your submodules
|
||||
using the 'status' subcommand and get a detailed overview of the
|
||||
difference between the index and checkouts using the 'summary'
|
||||
subcommand.
|
||||
|
||||
|
||||
COMMANDS
|
||||
--------
|
||||
add::
|
||||
@@ -56,10 +98,15 @@ status::
|
||||
repository. This command is the default command for 'git-submodule'.
|
||||
|
||||
init::
|
||||
Initialize the submodules, i.e. register in .git/config each submodule
|
||||
name and url found in .gitmodules. The key used in .git/config is
|
||||
`submodule.$name.url`. This command does not alter existing information
|
||||
in .git/config.
|
||||
Initialize the submodules, i.e. register each submodule name
|
||||
and url found in .gitmodules into .git/config.
|
||||
The key used in .git/config is `submodule.$name.url`.
|
||||
This command does not alter existing information in .git/config.
|
||||
You can then customize the submodule clone URLs in .git/config
|
||||
for your local setup and proceed to 'git submodule update';
|
||||
you can also just use 'git submodule update --init' without
|
||||
the explicit 'init' step if you do not intend to customize
|
||||
any submodule locations.
|
||||
|
||||
update::
|
||||
Update the registered submodules, i.e. clone missing submodules and
|
||||
|
||||
@@ -55,7 +55,7 @@ name is not a symbolic ref, or 128 if another error occurs.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
GIT
|
||||
---
|
||||
|
||||
@@ -9,7 +9,8 @@ git-tag - Create, list, delete or verify a tag object signed with GPG
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <name> [<head>]
|
||||
'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
|
||||
<name> [<commit> | <object>]
|
||||
'git tag' -d <name>...
|
||||
'git tag' [-n[<num>]] -l [<pattern>]
|
||||
'git tag' -v <name>...
|
||||
@@ -247,7 +248,7 @@ $ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>,
|
||||
Junio C Hamano <junkio@cox.net> and Chris Wright <chrisw@osdl.org>.
|
||||
Junio C Hamano <gitster@pobox.com> and Chris Wright <chrisw@osdl.org>.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -88,6 +88,16 @@ OPTIONS
|
||||
sometimes helpful when working with a big project on a
|
||||
filesystem that has very slow lstat(2) system call
|
||||
(e.g. cifs).
|
||||
+
|
||||
This option can be also used as a coarse file-level mechanism
|
||||
to ignore uncommitted changes in tracked files (akin to what
|
||||
`.gitignore` does for untracked files).
|
||||
You should remember that an explicit 'git add' operation will
|
||||
still cause the file to be refreshed from the working tree.
|
||||
Git will fail (gracefully) in case it needs to modify this file
|
||||
in the index e.g. when merging in a commit;
|
||||
thus, in case the assumed-untracked file is changed upstream,
|
||||
you will need to handle the situation manually.
|
||||
|
||||
-g::
|
||||
--again::
|
||||
|
||||
@@ -47,7 +47,7 @@ info/refs file unless `--force` flag is given.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -42,7 +42,7 @@ for objects that are deltified.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <junkio@cox.net>
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
||||
@@ -67,7 +67,7 @@ git whatchanged --since="2 weeks ago" \-- gitk::
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||
Junio C Hamano <junkio@cox.net>
|
||||
Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
|
||||
Documentation
|
||||
|
||||
@@ -43,12 +43,13 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.5.6.3/git.html[documentation for release 1.5.6.3]
|
||||
* link:v1.5.6.4/git.html[documentation for release 1.5.6.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.5.6.3.txt[1.5.6.3].
|
||||
link:RelNotes-1.5.6.2.txt[1.5.6.2].
|
||||
link:RelNotes-1.5.6.1.txt[1.5.6.1].
|
||||
link:RelNotes-1.5.6.4.txt[1.5.6.4],
|
||||
link:RelNotes-1.5.6.3.txt[1.5.6.3],
|
||||
link:RelNotes-1.5.6.2.txt[1.5.6.2],
|
||||
link:RelNotes-1.5.6.1.txt[1.5.6.1],
|
||||
link:RelNotes-1.5.6.txt[1.5.6].
|
||||
|
||||
* link:v1.5.5.4/git.html[documentation for release 1.5.5.4]
|
||||
|
||||
@@ -13,9 +13,14 @@ DESCRIPTION
|
||||
-----------
|
||||
|
||||
A `gitignore` file specifies intentionally untracked files that
|
||||
git should ignore. Each line in a `gitignore` file specifies a
|
||||
pattern.
|
||||
git should ignore.
|
||||
Note that all the `gitignore` files really concern only files
|
||||
that are not already tracked by git;
|
||||
in order to ignore uncommitted changes in already tracked files,
|
||||
please refer to the 'git update-index --assume-unchanged'
|
||||
documentation.
|
||||
|
||||
Each line in a `gitignore` file specifies a pattern.
|
||||
When deciding whether to ignore a path, git normally checks
|
||||
`gitignore` patterns from multiple sources, with the following
|
||||
order of precedence, from highest to lowest (within one level of
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From: Junio C Hamano <junkio@cox.net>
|
||||
From: Junio C Hamano <gitster@pobox.com>
|
||||
To: git@vger.kernel.org
|
||||
Cc: Petr Baudis <pasky@suse.cz>, Linus Torvalds <torvalds@osdl.org>
|
||||
Subject: Re: sending changesets from the middle of a git tree
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Subject: [HOWTO] Using post-update hook
|
||||
Message-ID: <7vy86o6usx.fsf@assigned-by-dhcp.cox.net>
|
||||
From: Junio C Hamano <junkio@cox.net>
|
||||
From: Junio C Hamano <gitster@pobox.com>
|
||||
Date: Fri, 26 Aug 2005 18:19:10 -0700
|
||||
Abstract: In this how-to article, JC talks about how he
|
||||
uses the post-update hook to automate git documentation page
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From: Junio C Hamano <junkio@cox.net>
|
||||
From: Junio C Hamano <gitster@pobox.com>
|
||||
To: git@vger.kernel.org
|
||||
Subject: [HOWTO] Reverting an existing commit
|
||||
Abstract: In this article, JC gives a small real-life example of using
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From: Junio C Hamano <junkio@cox.net>
|
||||
From: Junio C Hamano <gitster@pobox.com>
|
||||
Subject: Separating topic branches
|
||||
Abstract: In this article, JC describes how to separate topic branches.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From: Junio C Hamano <junkio@cox.net> and Carl Baldwin <cnb@fc.hp.com>
|
||||
From: Junio C Hamano <gitster@pobox.com> and Carl Baldwin <cnb@fc.hp.com>
|
||||
Subject: control access to branches.
|
||||
Date: Thu, 17 Nov 2005 23:55:32 -0800
|
||||
Message-ID: <7vfypumlu3.fsf@assigned-by-dhcp.cox.net>
|
||||
|
||||
@@ -112,9 +112,9 @@ options may be given. See linkgit:git-diff-files[1] for more options.
|
||||
--cc::
|
||||
|
||||
This flag implies the '-c' options and further compresses the
|
||||
patch output by omitting hunks that show differences from only
|
||||
one parent, or show the same change from all but one parent for
|
||||
an Octopus merge.
|
||||
patch output by omitting uninteresting hunks whose contents in
|
||||
the parents have only two variants and the merge result picks
|
||||
one of them without modification.
|
||||
|
||||
-r::
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
path-list API
|
||||
=============
|
||||
|
||||
The path_list API offers a data structure and functions to handle sorted
|
||||
and unsorted string lists.
|
||||
|
||||
The name is a bit misleading, a path_list may store not only paths but
|
||||
strings in general.
|
||||
|
||||
The caller:
|
||||
|
||||
. Allocates and clears a `struct path_list` variable.
|
||||
|
||||
. Initializes the members. You might want to set the flag `strdup_paths`
|
||||
if the strings should be strdup()ed. For example, this is necessary
|
||||
when you add something like git_path("..."), since that function returns
|
||||
a static buffer that will change with the next call to git_path().
|
||||
+
|
||||
If you need something advanced, you can manually malloc() the `items`
|
||||
member (you need this if you add things later) and you should set the
|
||||
`nr` and `alloc` members in that case, too.
|
||||
|
||||
. Adds new items to the list, using `path_list_append` or `path_list_insert`.
|
||||
|
||||
. Can check if a string is in the list using `path_list_has_path` or
|
||||
`unsorted_path_list_has_path` and get it from the list using
|
||||
`path_list_lookup` for sorted lists.
|
||||
|
||||
. Can sort an unsorted list using `sort_path_list`.
|
||||
|
||||
. Finally it should free the list using `path_list_clear`.
|
||||
|
||||
Example:
|
||||
|
||||
----
|
||||
struct path_list list;
|
||||
int i;
|
||||
|
||||
memset(&list, 0, sizeof(struct path_list));
|
||||
path_list_append("foo", &list);
|
||||
path_list_append("bar", &list);
|
||||
for (i = 0; i < list.nr; i++)
|
||||
printf("%s\n", list.items[i].path)
|
||||
----
|
||||
|
||||
NOTE: It is more efficient to build an unsorted list and sort it
|
||||
afterwards, instead of building a sorted list (`O(n log n)` instead of
|
||||
`O(n^2)`).
|
||||
+
|
||||
However, if you use the list to check if a certain string was added
|
||||
already, you should not do that (using unsorted_path_list_has_path()),
|
||||
because the complexity would be quadratic again (but with a worse factor).
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
* General ones (works with sorted and unsorted lists as well)
|
||||
|
||||
`print_path_list`::
|
||||
|
||||
Dump a path_list to stdout, useful mainly for debugging purposes. It
|
||||
can take an optional header argument and it writes out the
|
||||
string-pointer pairs of the path_list, each one in its own line.
|
||||
|
||||
`path_list_clear`::
|
||||
|
||||
Free a path_list. The `path` pointer of the items will be freed in case
|
||||
the `strdup_paths` member of the path_list is set. The second parameter
|
||||
controls if the `util` pointer of the items should be freed or not.
|
||||
|
||||
* Functions for sorted lists only
|
||||
|
||||
`path_list_has_path`::
|
||||
|
||||
Determine if the path_list has a given string or not.
|
||||
|
||||
`path_list_insert`::
|
||||
|
||||
Insert a new element to the path_list. The returned pointer can be handy
|
||||
if you want to write something to the `util` pointer of the
|
||||
path_list_item containing the just added string.
|
||||
+
|
||||
Since this function uses xrealloc() (which die()s if it fails) if the
|
||||
list needs to grow, it is safe not to check the pointer. I.e. you may
|
||||
write `path_list_insert(...)->util = ...;`.
|
||||
|
||||
`path_list_lookup`::
|
||||
|
||||
Look up a given string in the path_list, returning the containing
|
||||
path_list_item. If the string is not found, NULL is returned.
|
||||
|
||||
* Functions for unsorted lists only
|
||||
|
||||
`path_list_append`::
|
||||
|
||||
Append a new string to the end of the path_list.
|
||||
|
||||
`sort_path_list`::
|
||||
|
||||
Make an unsorted list sorted.
|
||||
|
||||
`unsorted_path_list_has_path`::
|
||||
|
||||
It's like `path_list_has_path()` but for unsorted lists.
|
||||
+
|
||||
This function needs to look through all items, as opposed to its
|
||||
counterpart for sorted lists, which performs a binary search.
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
* `struct path_list_item`
|
||||
|
||||
Represents an item of the list. The `path` member is a pointer to the
|
||||
string, and you may use the `util` member for any purpose, if you want.
|
||||
|
||||
* `struct path_list`
|
||||
|
||||
Represents the list itself.
|
||||
|
||||
. The array of items are available via the `items` member.
|
||||
. The `nr` member contains the number of items stored in the list.
|
||||
. The `alloc` member is used to avoid reallocating at every insertion.
|
||||
You should not tamper with it.
|
||||
. Setting the `strdup_paths` member to 1 will strdup() the strings
|
||||
before adding them, see above.
|
||||
@@ -30,7 +30,7 @@ Functions
|
||||
start_command() followed by finish_command(). Takes a pointer
|
||||
to a `struct child_process` that specifies the details.
|
||||
|
||||
`run_command_v_opt`, `run_command_v_opt_dir`, `run_command_v_opt_cd_env`::
|
||||
`run_command_v_opt`, `run_command_v_opt_cd`, `run_command_v_opt_cd_env`::
|
||||
|
||||
Convenience functions that encapsulate a sequence of
|
||||
start_command() followed by finish_command(). The argument argv
|
||||
|
||||
128
Documentation/technical/api-string-list.txt
Normal file
128
Documentation/technical/api-string-list.txt
Normal file
@@ -0,0 +1,128 @@
|
||||
string-list API
|
||||
===============
|
||||
|
||||
The string_list API offers a data structure and functions to handle sorted
|
||||
and unsorted string lists.
|
||||
|
||||
The 'string_list' struct used to be called 'path_list', but was renamed
|
||||
because it is not specific to paths.
|
||||
|
||||
The caller:
|
||||
|
||||
. Allocates and clears a `struct string_list` variable.
|
||||
|
||||
. Initializes the members. You might want to set the flag `strdup_strings`
|
||||
if the strings should be strdup()ed. For example, this is necessary
|
||||
when you add something like git_path("..."), since that function returns
|
||||
a static buffer that will change with the next call to git_path().
|
||||
+
|
||||
If you need something advanced, you can manually malloc() the `items`
|
||||
member (you need this if you add things later) and you should set the
|
||||
`nr` and `alloc` members in that case, too.
|
||||
|
||||
. Adds new items to the list, using `string_list_append` or
|
||||
`string_list_insert`.
|
||||
|
||||
. Can check if a string is in the list using `string_list_has_string` or
|
||||
`unsorted_string_list_has_string` and get it from the list using
|
||||
`string_list_lookup` for sorted lists.
|
||||
|
||||
. Can sort an unsorted list using `sort_string_list`.
|
||||
|
||||
. Finally it should free the list using `string_list_clear`.
|
||||
|
||||
Example:
|
||||
|
||||
----
|
||||
struct string_list list;
|
||||
int i;
|
||||
|
||||
memset(&list, 0, sizeof(struct string_list));
|
||||
string_list_append("foo", &list);
|
||||
string_list_append("bar", &list);
|
||||
for (i = 0; i < list.nr; i++)
|
||||
printf("%s\n", list.items[i].string)
|
||||
----
|
||||
|
||||
NOTE: It is more efficient to build an unsorted list and sort it
|
||||
afterwards, instead of building a sorted list (`O(n log n)` instead of
|
||||
`O(n^2)`).
|
||||
+
|
||||
However, if you use the list to check if a certain string was added
|
||||
already, you should not do that (using unsorted_string_list_has_string()),
|
||||
because the complexity would be quadratic again (but with a worse factor).
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
* General ones (works with sorted and unsorted lists as well)
|
||||
|
||||
`print_string_list`::
|
||||
|
||||
Dump a string_list to stdout, useful mainly for debugging purposes. It
|
||||
can take an optional header argument and it writes out the
|
||||
string-pointer pairs of the string_list, each one in its own line.
|
||||
|
||||
`string_list_clear`::
|
||||
|
||||
Free a string_list. The `string` pointer of the items will be freed in
|
||||
case the `strdup_strings` member of the string_list is set. The second
|
||||
parameter controls if the `util` pointer of the items should be freed
|
||||
or not.
|
||||
|
||||
* Functions for sorted lists only
|
||||
|
||||
`string_list_has_string`::
|
||||
|
||||
Determine if the string_list has a given string or not.
|
||||
|
||||
`string_list_insert`::
|
||||
|
||||
Insert a new element to the string_list. The returned pointer can be
|
||||
handy if you want to write something to the `util` pointer of the
|
||||
string_list_item containing the just added string.
|
||||
+
|
||||
Since this function uses xrealloc() (which die()s if it fails) if the
|
||||
list needs to grow, it is safe not to check the pointer. I.e. you may
|
||||
write `string_list_insert(...)->util = ...;`.
|
||||
|
||||
`string_list_lookup`::
|
||||
|
||||
Look up a given string in the string_list, returning the containing
|
||||
string_list_item. If the string is not found, NULL is returned.
|
||||
|
||||
* Functions for unsorted lists only
|
||||
|
||||
`string_list_append`::
|
||||
|
||||
Append a new string to the end of the string_list.
|
||||
|
||||
`sort_string_list`::
|
||||
|
||||
Make an unsorted list sorted.
|
||||
|
||||
`unsorted_string_list_has_string`::
|
||||
|
||||
It's like `string_list_has_string()` but for unsorted lists.
|
||||
+
|
||||
This function needs to look through all items, as opposed to its
|
||||
counterpart for sorted lists, which performs a binary search.
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
* `struct string_list_item`
|
||||
|
||||
Represents an item of the list. The `string` member is a pointer to the
|
||||
string, and you may use the `util` member for any purpose, if you want.
|
||||
|
||||
* `struct string_list`
|
||||
|
||||
Represents the list itself.
|
||||
|
||||
. The array of items are available via the `items` member.
|
||||
. The `nr` member contains the number of items stored in the list.
|
||||
. The `alloc` member is used to avoid reallocating at every insertion.
|
||||
You should not tamper with it.
|
||||
. Setting the `strdup_strings` member to 1 will strdup() the strings
|
||||
before adding them, see above.
|
||||
@@ -2431,7 +2431,7 @@ $ git rebase origin
|
||||
-------------------------------------------------
|
||||
|
||||
This will remove each of your commits from mywork, temporarily saving
|
||||
them as patches (in a directory named ".git/rebase"), update mywork to
|
||||
them as patches (in a directory named ".git/rebase-apply"), update mywork to
|
||||
point at the latest version of origin, then apply each of the saved
|
||||
patches to the new mywork. The result will look like:
|
||||
|
||||
|
||||
78
Makefile
78
Makefile
@@ -170,6 +170,16 @@ ALL_CFLAGS = $(CFLAGS)
|
||||
ALL_LDFLAGS = $(LDFLAGS)
|
||||
STRIP ?= strip
|
||||
|
||||
# Among the variables below, these:
|
||||
# gitexecdir
|
||||
# template_dir
|
||||
# htmldir
|
||||
# ETC_GITCONFIG (but not sysconfdir)
|
||||
# can be specified as a relative path ../some/where/else (which must begin
|
||||
# with ../); this is interpreted as relative to $(bindir) and "git" at
|
||||
# runtime figures out where they are based on the path to the executable.
|
||||
# This can help installing the suite in a relocatable way.
|
||||
|
||||
prefix =
|
||||
bindir = $(prefix)/bin
|
||||
mandir = $(prefix)/share/man
|
||||
@@ -205,7 +215,7 @@ GITWEB_FAVICON = git-favicon.png
|
||||
GITWEB_SITE_HEADER =
|
||||
GITWEB_SITE_FOOTER =
|
||||
|
||||
export prefix bindir gitexecdir sharedir htmldir sysconfdir
|
||||
export prefix bindir sharedir htmldir sysconfdir
|
||||
|
||||
CC = gcc
|
||||
AR = ar
|
||||
@@ -283,7 +293,6 @@ PROGRAMS += git-pack-redundant$X
|
||||
PROGRAMS += git-patch-id$X
|
||||
PROGRAMS += git-receive-pack$X
|
||||
PROGRAMS += git-send-pack$X
|
||||
PROGRAMS += git-shell$X
|
||||
PROGRAMS += git-show-index$X
|
||||
PROGRAMS += git-unpack-file$X
|
||||
PROGRAMS += git-update-server-info$X
|
||||
@@ -324,6 +333,7 @@ endif
|
||||
export PERL_PATH
|
||||
|
||||
LIB_FILE=libgit.a
|
||||
COMPAT_LIB = compat/lib.a
|
||||
XDIFF_LIB=xdiff/lib.a
|
||||
|
||||
LIB_H += archive.h
|
||||
@@ -355,7 +365,7 @@ LIB_H += pack-refs.h
|
||||
LIB_H += pack-revindex.h
|
||||
LIB_H += parse-options.h
|
||||
LIB_H += patch-ids.h
|
||||
LIB_H += path-list.h
|
||||
LIB_H += string-list.h
|
||||
LIB_H += pkt-line.h
|
||||
LIB_H += progress.h
|
||||
LIB_H += quote.h
|
||||
@@ -409,6 +419,7 @@ LIB_OBJS += diff-no-index.o
|
||||
LIB_OBJS += diff-lib.o
|
||||
LIB_OBJS += diff.o
|
||||
LIB_OBJS += dir.o
|
||||
LIB_OBJS += editor.o
|
||||
LIB_OBJS += entry.o
|
||||
LIB_OBJS += environment.o
|
||||
LIB_OBJS += exec_cmd.o
|
||||
@@ -436,7 +447,7 @@ LIB_OBJS += pager.o
|
||||
LIB_OBJS += parse-options.o
|
||||
LIB_OBJS += patch-delta.o
|
||||
LIB_OBJS += patch-ids.o
|
||||
LIB_OBJS += path-list.o
|
||||
LIB_OBJS += string-list.o
|
||||
LIB_OBJS += path.o
|
||||
LIB_OBJS += pkt-line.o
|
||||
LIB_OBJS += pretty.o
|
||||
@@ -744,9 +755,9 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
|
||||
COMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o compat/winansi.o
|
||||
EXTLIBS += -lws2_32
|
||||
X = .exe
|
||||
X = .exe
|
||||
NOEXECTEMPL = .noexec
|
||||
gitexecdir = $(bindir)
|
||||
gitexecdir = ../libexec/git-core
|
||||
template_dir = ../share/git-core/templates/
|
||||
ETC_GITCONFIG = ../etc/gitconfig
|
||||
htmldir=../doc/git/html/
|
||||
@@ -814,6 +825,7 @@ EXTLIBS += -lz
|
||||
ifndef NO_POSIX_ONLY_PROGRAMS
|
||||
PROGRAMS += git-daemon$X
|
||||
PROGRAMS += git-imap-send$X
|
||||
PROGRAMS += git-shell$X
|
||||
endif
|
||||
ifndef NO_OPENSSL
|
||||
OPENSSL_LIBSSL = -lssl
|
||||
@@ -1209,6 +1221,12 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
|
||||
|
||||
$(COMPAT_LIB): $(COMPAT_OBJS)
|
||||
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(COMPAT_OBJS)
|
||||
|
||||
git-shell$X: abspath.o ctype.o exec_cmd.o quote.o strbuf.o usage.o wrapper.o shell.o $(COMPAT_LIB)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(COMPAT_LIB)
|
||||
|
||||
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
|
||||
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
|
||||
builtin-revert.o wt-status.o: wt-status.h
|
||||
@@ -1254,8 +1272,12 @@ GIT-CFLAGS: .FORCE-GIT-CFLAGS
|
||||
echo "$$FLAGS" >GIT-CFLAGS; \
|
||||
fi
|
||||
|
||||
# We need to apply sq twice, once to protect from the shell
|
||||
# that runs GIT-BUILD-OPTIONS, and then again to protect it
|
||||
# and the first level quoting from the shell that runs "echo".
|
||||
GIT-BUILD-OPTIONS: .FORCE-GIT-BUILD-OPTIONS
|
||||
@echo SHELL_PATH=\''$(SHELL_PATH_SQ)'\' >$@
|
||||
@echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
|
||||
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
|
||||
|
||||
### Detect Tck/Tk interpreter path changes
|
||||
ifndef NO_TCLTK
|
||||
@@ -1304,41 +1326,49 @@ check: common-cmds.h
|
||||
for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
|
||||
|
||||
remove-dashes:
|
||||
./fixup-builtins $(BUILT_INS)
|
||||
./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
|
||||
|
||||
### Installation rules
|
||||
|
||||
ifeq ($(firstword $(subst /, ,$(template_dir))),..)
|
||||
template_instdir = $(gitexecdir)/$(template_dir)
|
||||
template_instdir = $(bindir)/$(template_dir)
|
||||
else
|
||||
template_instdir = $(template_dir)
|
||||
endif
|
||||
export template_instdir
|
||||
|
||||
ifeq ($(firstword $(subst /, ,$(gitexecdir))),..)
|
||||
gitexec_instdir = $(bindir)/$(gitexecdir)
|
||||
else
|
||||
gitexec_instdir = $(gitexecdir)
|
||||
endif
|
||||
gitexec_instdir_SQ = $(subst ','\'',$(gitexec_instdir))
|
||||
export gitexec_instdir
|
||||
|
||||
install: all
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexecdir_SQ)'
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)'
|
||||
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
|
||||
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
|
||||
$(INSTALL) git$X git-upload-pack$X git-receive-pack$X git-upload-archive$X '$(DESTDIR_SQ)$(bindir_SQ)'
|
||||
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
|
||||
$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
|
||||
ifndef NO_TCLTK
|
||||
$(MAKE) -C gitk-git install
|
||||
$(MAKE) -C git-gui install
|
||||
$(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install
|
||||
endif
|
||||
if test 'z$(bindir_SQ)' != 'z$(gitexecdir_SQ)'; \
|
||||
then \
|
||||
ln -f '$(DESTDIR_SQ)$(bindir_SQ)/git$X' \
|
||||
'$(DESTDIR_SQ)$(gitexecdir_SQ)/git$X' || \
|
||||
cp '$(DESTDIR_SQ)$(bindir_SQ)/git$X' \
|
||||
'$(DESTDIR_SQ)$(gitexecdir_SQ)/git$X'; \
|
||||
fi
|
||||
$(foreach p,$(BUILT_INS), $(RM) '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' && ln '$(DESTDIR_SQ)$(gitexecdir_SQ)/git$X' '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' ;)
|
||||
ifneq (,$X)
|
||||
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p';)
|
||||
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
|
||||
endif
|
||||
./check_bindir 'z$(bindir_SQ)' 'z$(gitexecdir_SQ)' '$(DESTDIR_SQ)$(bindir_SQ)/git-shell$X'
|
||||
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
|
||||
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
|
||||
if test "z$$bindir" != "z$$execdir"; \
|
||||
then \
|
||||
ln -f "$$bindir/git$X" "$$execdir/git$X" || \
|
||||
cp "$$bindir/git$X" "$$execdir/git$X"; \
|
||||
fi && \
|
||||
{ $(foreach p,$(BUILT_INS), $(RM) "$$execdir/$p" && ln "$$execdir/git$X" "$$execdir/$p" ;) } && \
|
||||
$(RM) "$$execdir/git$X" && \
|
||||
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
|
||||
|
||||
install-doc:
|
||||
$(MAKE) -C Documentation install
|
||||
@@ -1406,7 +1436,7 @@ distclean: clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \
|
||||
$(LIB_FILE) $(XDIFF_LIB)
|
||||
$(LIB_FILE) $(XDIFF_LIB) $(COMPAT_LIB)
|
||||
$(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
|
||||
$(RM) $(TEST_PROGRAMS)
|
||||
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
|
||||
|
||||
36
abspath.c
36
abspath.c
@@ -66,3 +66,39 @@ const char *make_absolute_path(const char *path)
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *get_pwd_cwd(void)
|
||||
{
|
||||
static char cwd[PATH_MAX + 1];
|
||||
char *pwd;
|
||||
struct stat cwd_stat, pwd_stat;
|
||||
if (getcwd(cwd, PATH_MAX) == NULL)
|
||||
return NULL;
|
||||
pwd = getenv("PWD");
|
||||
if (pwd && strcmp(pwd, cwd)) {
|
||||
stat(cwd, &cwd_stat);
|
||||
if (!stat(pwd, &pwd_stat) &&
|
||||
pwd_stat.st_dev == cwd_stat.st_dev &&
|
||||
pwd_stat.st_ino == cwd_stat.st_ino) {
|
||||
strlcpy(cwd, pwd, PATH_MAX);
|
||||
}
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
const char *make_nonrelative_path(const char *path)
|
||||
{
|
||||
static char buf[PATH_MAX + 1];
|
||||
|
||||
if (is_absolute_path(path)) {
|
||||
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
|
||||
die("Too long path: %.*s", 60, path);
|
||||
} else {
|
||||
const char *cwd = get_pwd_cwd();
|
||||
if (!cwd)
|
||||
die("Cannot determine the current working directory");
|
||||
if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
|
||||
die("Too long path: %.*s", 60, path);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
117
archive-tar.c
117
archive-tar.c
@@ -2,9 +2,7 @@
|
||||
* Copyright (c) 2005, 2006 Rene Scharfe
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "tar.h"
|
||||
#include "builtin.h"
|
||||
#include "archive.h"
|
||||
|
||||
#define RECORDSIZE (512)
|
||||
@@ -13,11 +11,7 @@
|
||||
static char block[BLOCKSIZE];
|
||||
static unsigned long offset;
|
||||
|
||||
static time_t archive_time;
|
||||
static int tar_umask = 002;
|
||||
static int verbose;
|
||||
static const struct commit *commit;
|
||||
static size_t base_len;
|
||||
|
||||
/* writes out the whole block, but only if it is full */
|
||||
static void write_if_needed(void)
|
||||
@@ -114,22 +108,24 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header)
|
||||
return chksum;
|
||||
}
|
||||
|
||||
static int get_path_prefix(const struct strbuf *path, int maxlen)
|
||||
static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen)
|
||||
{
|
||||
int i = path->len;
|
||||
size_t i = pathlen;
|
||||
if (i > maxlen)
|
||||
i = maxlen;
|
||||
do {
|
||||
i--;
|
||||
} while (i > 0 && path->buf[i] != '/');
|
||||
} while (i > 0 && path[i] != '/');
|
||||
return i;
|
||||
}
|
||||
|
||||
static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
unsigned int mode, void *buffer, unsigned long size)
|
||||
static int write_tar_entry(struct archiver_args *args,
|
||||
const unsigned char *sha1, const char *path, size_t pathlen,
|
||||
unsigned int mode, void *buffer, unsigned long size)
|
||||
{
|
||||
struct ustar_header header;
|
||||
struct strbuf ext_header;
|
||||
int err = 0;
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
strbuf_init(&ext_header, 0);
|
||||
@@ -143,8 +139,6 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
mode = 0100666;
|
||||
sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
|
||||
} else {
|
||||
if (verbose)
|
||||
fprintf(stderr, "%.*s\n", (int)path->len, path->buf);
|
||||
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
||||
*header.typeflag = TYPEFLAG_DIR;
|
||||
mode = (mode | 0777) & ~tar_umask;
|
||||
@@ -155,24 +149,24 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
*header.typeflag = TYPEFLAG_REG;
|
||||
mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
|
||||
} else {
|
||||
error("unsupported file mode: 0%o (SHA1: %s)",
|
||||
mode, sha1_to_hex(sha1));
|
||||
return;
|
||||
return error("unsupported file mode: 0%o (SHA1: %s)",
|
||||
mode, sha1_to_hex(sha1));
|
||||
}
|
||||
if (path->len > sizeof(header.name)) {
|
||||
int plen = get_path_prefix(path, sizeof(header.prefix));
|
||||
int rest = path->len - plen - 1;
|
||||
if (pathlen > sizeof(header.name)) {
|
||||
size_t plen = get_path_prefix(path, pathlen,
|
||||
sizeof(header.prefix));
|
||||
size_t rest = pathlen - plen - 1;
|
||||
if (plen > 0 && rest <= sizeof(header.name)) {
|
||||
memcpy(header.prefix, path->buf, plen);
|
||||
memcpy(header.name, path->buf + plen + 1, rest);
|
||||
memcpy(header.prefix, path, plen);
|
||||
memcpy(header.name, path + plen + 1, rest);
|
||||
} else {
|
||||
sprintf(header.name, "%s.data",
|
||||
sha1_to_hex(sha1));
|
||||
strbuf_append_ext_header(&ext_header, "path",
|
||||
path->buf, path->len);
|
||||
path, pathlen);
|
||||
}
|
||||
} else
|
||||
memcpy(header.name, path->buf, path->len);
|
||||
memcpy(header.name, path, pathlen);
|
||||
}
|
||||
|
||||
if (S_ISLNK(mode) && buffer) {
|
||||
@@ -187,7 +181,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
|
||||
sprintf(header.mode, "%07o", mode & 07777);
|
||||
sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
|
||||
sprintf(header.mtime, "%011lo", archive_time);
|
||||
sprintf(header.mtime, "%011lo", args->time);
|
||||
|
||||
sprintf(header.uid, "%07o", 0);
|
||||
sprintf(header.gid, "%07o", 0);
|
||||
@@ -202,22 +196,30 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
sprintf(header.chksum, "%07o", ustar_header_chksum(&header));
|
||||
|
||||
if (ext_header.len > 0) {
|
||||
write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len);
|
||||
err = write_tar_entry(args, sha1, NULL, 0, 0, ext_header.buf,
|
||||
ext_header.len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
strbuf_release(&ext_header);
|
||||
write_blocked(&header, sizeof(header));
|
||||
if (S_ISREG(mode) && buffer && size > 0)
|
||||
write_blocked(buffer, size);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void write_global_extended_header(const unsigned char *sha1)
|
||||
static int write_global_extended_header(struct archiver_args *args)
|
||||
{
|
||||
const unsigned char *sha1 = args->commit_sha1;
|
||||
struct strbuf ext_header;
|
||||
int err;
|
||||
|
||||
strbuf_init(&ext_header, 0);
|
||||
strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
|
||||
write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len);
|
||||
err = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf,
|
||||
ext_header.len);
|
||||
strbuf_release(&ext_header);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int git_tar_config(const char *var, const char *value, void *cb)
|
||||
@@ -234,64 +236,17 @@ static int git_tar_config(const char *var, const char *value, void *cb)
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static int write_tar_entry(const unsigned char *sha1,
|
||||
const char *base, int baselen,
|
||||
const char *filename, unsigned mode, int stage)
|
||||
{
|
||||
static struct strbuf path = STRBUF_INIT;
|
||||
void *buffer;
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
|
||||
strbuf_reset(&path);
|
||||
strbuf_grow(&path, PATH_MAX);
|
||||
strbuf_add(&path, base, baselen);
|
||||
strbuf_addstr(&path, filename);
|
||||
if (is_archive_path_ignored(path.buf + base_len))
|
||||
return 0;
|
||||
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
||||
strbuf_addch(&path, '/');
|
||||
buffer = NULL;
|
||||
size = 0;
|
||||
} else {
|
||||
buffer = sha1_file_to_archive(path.buf + base_len, sha1, mode,
|
||||
&type, &size, commit);
|
||||
if (!buffer)
|
||||
die("cannot read %s", sha1_to_hex(sha1));
|
||||
}
|
||||
|
||||
write_entry(sha1, &path, mode, buffer, size);
|
||||
free(buffer);
|
||||
|
||||
return READ_TREE_RECURSIVE;
|
||||
}
|
||||
|
||||
int write_tar_archive(struct archiver_args *args)
|
||||
{
|
||||
int plen = args->base ? strlen(args->base) : 0;
|
||||
int err = 0;
|
||||
|
||||
git_config(git_tar_config, NULL);
|
||||
|
||||
archive_time = args->time;
|
||||
verbose = args->verbose;
|
||||
commit = args->commit;
|
||||
base_len = args->base ? strlen(args->base) : 0;
|
||||
|
||||
if (args->commit_sha1)
|
||||
write_global_extended_header(args->commit_sha1);
|
||||
|
||||
if (args->base && plen > 0 && args->base[plen - 1] == '/') {
|
||||
char *base = xstrdup(args->base);
|
||||
int baselen = strlen(base);
|
||||
|
||||
while (baselen > 0 && base[baselen - 1] == '/')
|
||||
base[--baselen] = '\0';
|
||||
write_tar_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
|
||||
free(base);
|
||||
}
|
||||
read_tree_recursive(args->tree, args->base, plen, 0,
|
||||
args->pathspec, write_tar_entry);
|
||||
write_trailer();
|
||||
|
||||
return 0;
|
||||
err = write_global_extended_header(args);
|
||||
if (!err)
|
||||
err = write_archive_entries(args, write_tar_entry);
|
||||
if (!err)
|
||||
write_trailer();
|
||||
return err;
|
||||
}
|
||||
|
||||
114
archive-zip.c
114
archive-zip.c
@@ -2,18 +2,10 @@
|
||||
* Copyright (c) 2006 Rene Scharfe
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "blob.h"
|
||||
#include "tree.h"
|
||||
#include "quote.h"
|
||||
#include "builtin.h"
|
||||
#include "archive.h"
|
||||
|
||||
static int verbose;
|
||||
static int zip_date;
|
||||
static int zip_time;
|
||||
static const struct commit *commit;
|
||||
static size_t base_len;
|
||||
|
||||
static unsigned char *zip_dir;
|
||||
static unsigned int zip_dir_size;
|
||||
@@ -96,7 +88,7 @@ static void copy_le32(unsigned char *dest, unsigned int n)
|
||||
}
|
||||
|
||||
static void *zlib_deflate(void *data, unsigned long size,
|
||||
unsigned long *compressed_size)
|
||||
int compression_level, unsigned long *compressed_size)
|
||||
{
|
||||
z_stream stream;
|
||||
unsigned long maxsize;
|
||||
@@ -104,7 +96,7 @@ static void *zlib_deflate(void *data, unsigned long size,
|
||||
int result;
|
||||
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
deflateInit(&stream, zlib_compression_level);
|
||||
deflateInit(&stream, compression_level);
|
||||
maxsize = deflateBound(&stream, size);
|
||||
buffer = xmalloc(maxsize);
|
||||
|
||||
@@ -128,33 +120,9 @@ static void *zlib_deflate(void *data, unsigned long size,
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *construct_path(const char *base, int baselen,
|
||||
const char *filename, int isdir, int *pathlen)
|
||||
{
|
||||
int filenamelen = strlen(filename);
|
||||
int len = baselen + filenamelen;
|
||||
char *path, *p;
|
||||
|
||||
if (isdir)
|
||||
len++;
|
||||
p = path = xmalloc(len + 1);
|
||||
|
||||
memcpy(p, base, baselen);
|
||||
p += baselen;
|
||||
memcpy(p, filename, filenamelen);
|
||||
p += filenamelen;
|
||||
if (isdir)
|
||||
*p++ = '/';
|
||||
*p = '\0';
|
||||
|
||||
*pathlen = len;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static int write_zip_entry(const unsigned char *sha1,
|
||||
const char *base, int baselen,
|
||||
const char *filename, unsigned mode, int stage)
|
||||
static int write_zip_entry(struct archiver_args *args,
|
||||
const unsigned char *sha1, const char *path, size_t pathlen,
|
||||
unsigned int mode, void *buffer, unsigned long size)
|
||||
{
|
||||
struct zip_local_header header;
|
||||
struct zip_dir_header dirent;
|
||||
@@ -163,33 +131,20 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
unsigned long uncompressed_size;
|
||||
unsigned long crc;
|
||||
unsigned long direntsize;
|
||||
unsigned long size;
|
||||
int method;
|
||||
int result = -1;
|
||||
int pathlen;
|
||||
unsigned char *out;
|
||||
char *path;
|
||||
enum object_type type;
|
||||
void *buffer = NULL;
|
||||
void *deflated = NULL;
|
||||
|
||||
crc = crc32(0, NULL, 0);
|
||||
|
||||
path = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen);
|
||||
if (is_archive_path_ignored(path + base_len))
|
||||
return 0;
|
||||
if (verbose)
|
||||
fprintf(stderr, "%s\n", path);
|
||||
if (pathlen > 0xffff) {
|
||||
error("path too long (%d chars, SHA1: %s): %s", pathlen,
|
||||
sha1_to_hex(sha1), path);
|
||||
goto out;
|
||||
return error("path too long (%d chars, SHA1: %s): %s",
|
||||
(int)pathlen, sha1_to_hex(sha1), path);
|
||||
}
|
||||
|
||||
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
||||
method = 0;
|
||||
attr2 = 16;
|
||||
result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
|
||||
out = NULL;
|
||||
uncompressed_size = 0;
|
||||
compressed_size = 0;
|
||||
@@ -197,25 +152,20 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
method = 0;
|
||||
attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
|
||||
(mode & 0111) ? ((mode) << 16) : 0;
|
||||
if (S_ISREG(mode) && zlib_compression_level != 0)
|
||||
if (S_ISREG(mode) && args->compression_level != 0)
|
||||
method = 8;
|
||||
result = 0;
|
||||
buffer = sha1_file_to_archive(path + base_len, sha1, mode,
|
||||
&type, &size, commit);
|
||||
if (!buffer)
|
||||
die("cannot read %s", sha1_to_hex(sha1));
|
||||
crc = crc32(crc, buffer, size);
|
||||
out = buffer;
|
||||
uncompressed_size = size;
|
||||
compressed_size = size;
|
||||
} else {
|
||||
error("unsupported file mode: 0%o (SHA1: %s)", mode,
|
||||
sha1_to_hex(sha1));
|
||||
goto out;
|
||||
return error("unsupported file mode: 0%o (SHA1: %s)", mode,
|
||||
sha1_to_hex(sha1));
|
||||
}
|
||||
|
||||
if (method == 8) {
|
||||
deflated = zlib_deflate(buffer, size, &compressed_size);
|
||||
deflated = zlib_deflate(buffer, size, args->compression_level,
|
||||
&compressed_size);
|
||||
if (deflated && compressed_size - 6 < size) {
|
||||
/* ZLIB --> raw compressed data (see RFC 1950) */
|
||||
/* CMF and FLG ... */
|
||||
@@ -278,12 +228,9 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
zip_offset += compressed_size;
|
||||
}
|
||||
|
||||
out:
|
||||
free(buffer);
|
||||
free(deflated);
|
||||
free(path);
|
||||
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void write_zip_trailer(const unsigned char *sha1)
|
||||
@@ -316,43 +263,18 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)
|
||||
|
||||
int write_zip_archive(struct archiver_args *args)
|
||||
{
|
||||
int plen = strlen(args->base);
|
||||
int err;
|
||||
|
||||
dos_time(&args->time, &zip_date, &zip_time);
|
||||
|
||||
zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
|
||||
zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
|
||||
verbose = args->verbose;
|
||||
commit = args->commit;
|
||||
base_len = args->base ? strlen(args->base) : 0;
|
||||
|
||||
if (args->base && plen > 0 && args->base[plen - 1] == '/') {
|
||||
char *base = xstrdup(args->base);
|
||||
int baselen = strlen(base);
|
||||
|
||||
while (baselen > 0 && base[baselen - 1] == '/')
|
||||
base[--baselen] = '\0';
|
||||
write_zip_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
|
||||
free(base);
|
||||
}
|
||||
read_tree_recursive(args->tree, args->base, plen, 0,
|
||||
args->pathspec, write_zip_entry);
|
||||
write_zip_trailer(args->commit_sha1);
|
||||
err = write_archive_entries(args, write_zip_entry);
|
||||
if (!err)
|
||||
write_zip_trailer(args->commit_sha1);
|
||||
|
||||
free(zip_dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *parse_extra_zip_args(int argc, const char **argv)
|
||||
{
|
||||
for (; argc > 0; argc--, argv++) {
|
||||
const char *arg = argv[0];
|
||||
|
||||
if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0')
|
||||
zlib_compression_level = arg[1] - '0';
|
||||
else
|
||||
die("Unknown argument for zip format: %s", arg);
|
||||
}
|
||||
return NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
291
archive.c
291
archive.c
@@ -1,6 +1,22 @@
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "tree-walk.h"
|
||||
#include "attr.h"
|
||||
#include "archive.h"
|
||||
|
||||
static const char archive_usage[] = \
|
||||
"git archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
|
||||
|
||||
#define USES_ZLIB_COMPRESSION 1
|
||||
|
||||
const struct archiver {
|
||||
const char *name;
|
||||
write_archive_fn_t write_archive;
|
||||
unsigned int flags;
|
||||
} archivers[] = {
|
||||
{ "tar", write_tar_archive },
|
||||
{ "zip", write_zip_archive, USES_ZLIB_COMPRESSION },
|
||||
};
|
||||
|
||||
static void format_subst(const struct commit *commit,
|
||||
const char *src, size_t len,
|
||||
@@ -35,34 +51,9 @@ static void format_subst(const struct commit *commit,
|
||||
free(to_free);
|
||||
}
|
||||
|
||||
static int convert_to_archive(const char *path,
|
||||
const void *src, size_t len,
|
||||
struct strbuf *buf,
|
||||
const struct commit *commit)
|
||||
{
|
||||
static struct git_attr *attr_export_subst;
|
||||
struct git_attr_check check[1];
|
||||
|
||||
if (!commit)
|
||||
return 0;
|
||||
|
||||
if (!attr_export_subst)
|
||||
attr_export_subst = git_attr("export-subst", 12);
|
||||
|
||||
check[0].attr = attr_export_subst;
|
||||
if (git_checkattr(path, ARRAY_SIZE(check), check))
|
||||
return 0;
|
||||
if (!ATTR_TRUE(check[0].value))
|
||||
return 0;
|
||||
|
||||
format_subst(commit, src, len, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
|
||||
unsigned int mode, enum object_type *type,
|
||||
unsigned long *sizep,
|
||||
const struct commit *commit)
|
||||
static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
|
||||
unsigned int mode, enum object_type *type,
|
||||
unsigned long *sizep, const struct commit *commit)
|
||||
{
|
||||
void *buffer;
|
||||
|
||||
@@ -74,7 +65,8 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
|
||||
strbuf_init(&buf, 0);
|
||||
strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
|
||||
convert_to_working_tree(path, buf.buf, buf.len, &buf);
|
||||
convert_to_archive(path, buf.buf, buf.len, &buf, commit);
|
||||
if (commit)
|
||||
format_subst(commit, buf.buf, buf.len, &buf);
|
||||
buffer = strbuf_detach(&buf, &size);
|
||||
*sizep = size;
|
||||
}
|
||||
@@ -82,16 +74,243 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int is_archive_path_ignored(const char *path)
|
||||
static void setup_archive_check(struct git_attr_check *check)
|
||||
{
|
||||
static struct git_attr *attr_export_ignore;
|
||||
struct git_attr_check check[1];
|
||||
static struct git_attr *attr_export_subst;
|
||||
|
||||
if (!attr_export_ignore)
|
||||
if (!attr_export_ignore) {
|
||||
attr_export_ignore = git_attr("export-ignore", 13);
|
||||
|
||||
attr_export_subst = git_attr("export-subst", 12);
|
||||
}
|
||||
check[0].attr = attr_export_ignore;
|
||||
if (git_checkattr(path, ARRAY_SIZE(check), check))
|
||||
return 0;
|
||||
return ATTR_TRUE(check[0].value);
|
||||
check[1].attr = attr_export_subst;
|
||||
}
|
||||
|
||||
struct archiver_context {
|
||||
struct archiver_args *args;
|
||||
write_archive_entry_fn_t write_entry;
|
||||
};
|
||||
|
||||
static int write_archive_entry(const unsigned char *sha1, const char *base,
|
||||
int baselen, const char *filename, unsigned mode, int stage,
|
||||
void *context)
|
||||
{
|
||||
static struct strbuf path = STRBUF_INIT;
|
||||
struct archiver_context *c = context;
|
||||
struct archiver_args *args = c->args;
|
||||
write_archive_entry_fn_t write_entry = c->write_entry;
|
||||
struct git_attr_check check[2];
|
||||
const char *path_without_prefix;
|
||||
int convert = 0;
|
||||
int err;
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
void *buffer;
|
||||
|
||||
strbuf_reset(&path);
|
||||
strbuf_grow(&path, PATH_MAX);
|
||||
strbuf_add(&path, base, baselen);
|
||||
strbuf_addstr(&path, filename);
|
||||
path_without_prefix = path.buf + args->baselen;
|
||||
|
||||
setup_archive_check(check);
|
||||
if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {
|
||||
if (ATTR_TRUE(check[0].value))
|
||||
return 0;
|
||||
convert = ATTR_TRUE(check[1].value);
|
||||
}
|
||||
|
||||
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
||||
strbuf_addch(&path, '/');
|
||||
if (args->verbose)
|
||||
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
|
||||
err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);
|
||||
if (err)
|
||||
return err;
|
||||
return READ_TREE_RECURSIVE;
|
||||
}
|
||||
|
||||
buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
|
||||
&type, &size, convert ? args->commit : NULL);
|
||||
if (!buffer)
|
||||
return error("cannot read %s", sha1_to_hex(sha1));
|
||||
if (args->verbose)
|
||||
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
|
||||
err = write_entry(args, sha1, path.buf, path.len, mode, buffer, size);
|
||||
free(buffer);
|
||||
return err;
|
||||
}
|
||||
|
||||
int write_archive_entries(struct archiver_args *args,
|
||||
write_archive_entry_fn_t write_entry)
|
||||
{
|
||||
struct archiver_context context;
|
||||
int err;
|
||||
|
||||
if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
|
||||
size_t len = args->baselen;
|
||||
|
||||
while (len > 1 && args->base[len - 2] == '/')
|
||||
len--;
|
||||
if (args->verbose)
|
||||
fprintf(stderr, "%.*s\n", (int)len, args->base);
|
||||
err = write_entry(args, args->tree->object.sha1, args->base,
|
||||
len, 040777, NULL, 0);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
context.args = args;
|
||||
context.write_entry = write_entry;
|
||||
|
||||
err = read_tree_recursive(args->tree, args->base, args->baselen, 0,
|
||||
args->pathspec, write_archive_entry, &context);
|
||||
if (err == READ_TREE_RECURSIVE)
|
||||
err = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct archiver *lookup_archiver(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(archivers); i++) {
|
||||
if (!strcmp(name, archivers[i].name))
|
||||
return &archivers[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void parse_pathspec_arg(const char **pathspec,
|
||||
struct archiver_args *ar_args)
|
||||
{
|
||||
ar_args->pathspec = get_pathspec(ar_args->base, pathspec);
|
||||
}
|
||||
|
||||
static void parse_treeish_arg(const char **argv,
|
||||
struct archiver_args *ar_args, const char *prefix)
|
||||
{
|
||||
const char *name = argv[0];
|
||||
const unsigned char *commit_sha1;
|
||||
time_t archive_time;
|
||||
struct tree *tree;
|
||||
const struct commit *commit;
|
||||
unsigned char sha1[20];
|
||||
|
||||
if (get_sha1(name, sha1))
|
||||
die("Not a valid object name");
|
||||
|
||||
commit = lookup_commit_reference_gently(sha1, 1);
|
||||
if (commit) {
|
||||
commit_sha1 = commit->object.sha1;
|
||||
archive_time = commit->date;
|
||||
} else {
|
||||
commit_sha1 = NULL;
|
||||
archive_time = time(NULL);
|
||||
}
|
||||
|
||||
tree = parse_tree_indirect(sha1);
|
||||
if (tree == NULL)
|
||||
die("not a tree object");
|
||||
|
||||
if (prefix) {
|
||||
unsigned char tree_sha1[20];
|
||||
unsigned int mode;
|
||||
int err;
|
||||
|
||||
err = get_tree_entry(tree->object.sha1, prefix,
|
||||
tree_sha1, &mode);
|
||||
if (err || !S_ISDIR(mode))
|
||||
die("current working directory is untracked");
|
||||
|
||||
tree = parse_tree_indirect(tree_sha1);
|
||||
}
|
||||
ar_args->tree = tree;
|
||||
ar_args->commit_sha1 = commit_sha1;
|
||||
ar_args->commit = commit;
|
||||
ar_args->time = archive_time;
|
||||
}
|
||||
|
||||
static int parse_archive_args(int argc, const char **argv,
|
||||
const struct archiver **ar, struct archiver_args *args)
|
||||
{
|
||||
const char *format = "tar";
|
||||
const char *base = "";
|
||||
int compression_level = -1;
|
||||
int verbose = 0;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
if (!strcmp(arg, "--list") || !strcmp(arg, "-l")) {
|
||||
for (i = 0; i < ARRAY_SIZE(archivers); i++)
|
||||
printf("%s\n", archivers[i].name);
|
||||
exit(0);
|
||||
}
|
||||
if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) {
|
||||
verbose = 1;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--format=")) {
|
||||
format = arg + 9;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--prefix=")) {
|
||||
base = arg + 9;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--")) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0') {
|
||||
compression_level = arg[1] - '0';
|
||||
continue;
|
||||
}
|
||||
if (arg[0] == '-')
|
||||
die("Unknown argument: %s", arg);
|
||||
break;
|
||||
}
|
||||
|
||||
/* We need at least one parameter -- tree-ish */
|
||||
if (argc - 1 < i)
|
||||
usage(archive_usage);
|
||||
*ar = lookup_archiver(format);
|
||||
if (!*ar)
|
||||
die("Unknown archive format '%s'", format);
|
||||
|
||||
args->compression_level = Z_DEFAULT_COMPRESSION;
|
||||
if (compression_level != -1) {
|
||||
if ((*ar)->flags & USES_ZLIB_COMPRESSION)
|
||||
args->compression_level = compression_level;
|
||||
else {
|
||||
die("Argument not supported for format '%s': -%d",
|
||||
format, compression_level);
|
||||
}
|
||||
}
|
||||
args->verbose = verbose;
|
||||
args->base = base;
|
||||
args->baselen = strlen(base);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int write_archive(int argc, const char **argv, const char *prefix,
|
||||
int setup_prefix)
|
||||
{
|
||||
const struct archiver *ar = NULL;
|
||||
struct archiver_args args;
|
||||
int tree_idx;
|
||||
|
||||
tree_idx = parse_archive_args(argc, argv, &ar, &args);
|
||||
if (setup_prefix && prefix == NULL)
|
||||
prefix = setup_git_directory();
|
||||
|
||||
argv += tree_idx;
|
||||
parse_treeish_arg(argv, &args, prefix);
|
||||
parse_pathspec_arg(argv + 1, &args);
|
||||
|
||||
return ar->write_archive(&args);
|
||||
}
|
||||
|
||||
30
archive.h
30
archive.h
@@ -1,49 +1,29 @@
|
||||
#ifndef ARCHIVE_H
|
||||
#define ARCHIVE_H
|
||||
|
||||
#define MAX_EXTRA_ARGS 32
|
||||
#define MAX_ARGS (MAX_EXTRA_ARGS + 32)
|
||||
|
||||
struct archiver_args {
|
||||
const char *base;
|
||||
size_t baselen;
|
||||
struct tree *tree;
|
||||
const unsigned char *commit_sha1;
|
||||
const struct commit *commit;
|
||||
time_t time;
|
||||
const char **pathspec;
|
||||
unsigned int verbose : 1;
|
||||
void *extra;
|
||||
int compression_level;
|
||||
};
|
||||
|
||||
typedef int (*write_archive_fn_t)(struct archiver_args *);
|
||||
|
||||
typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);
|
||||
typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);
|
||||
|
||||
struct archiver {
|
||||
const char *name;
|
||||
struct archiver_args args;
|
||||
write_archive_fn_t write_archive;
|
||||
parse_extra_args_fn_t parse_extra;
|
||||
};
|
||||
|
||||
extern int parse_archive_args(int argc,
|
||||
const char **argv,
|
||||
struct archiver *ar);
|
||||
|
||||
extern void parse_treeish_arg(const char **treeish,
|
||||
struct archiver_args *ar_args,
|
||||
const char *prefix);
|
||||
|
||||
extern void parse_pathspec_arg(const char **pathspec,
|
||||
struct archiver_args *args);
|
||||
/*
|
||||
* Archive-format specific backends.
|
||||
*/
|
||||
extern int write_tar_archive(struct archiver_args *);
|
||||
extern int write_zip_archive(struct archiver_args *);
|
||||
extern void *parse_extra_zip_args(int argc, const char **argv);
|
||||
|
||||
extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit);
|
||||
extern int is_archive_path_ignored(const char *path);
|
||||
extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
|
||||
extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix);
|
||||
|
||||
#endif /* ARCHIVE_H */
|
||||
|
||||
15
attr.c
15
attr.c
@@ -459,7 +459,9 @@ static void prepare_attr_stack(const char *path, int dirlen)
|
||||
{
|
||||
struct attr_stack *elem, *info;
|
||||
int len;
|
||||
char pathbuf[PATH_MAX];
|
||||
struct strbuf pathbuf;
|
||||
|
||||
strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
|
||||
|
||||
/*
|
||||
* At the bottom of the attribute stack is the built-in
|
||||
@@ -510,13 +512,14 @@ static void prepare_attr_stack(const char *path, int dirlen)
|
||||
len = strlen(attr_stack->origin);
|
||||
if (dirlen <= len)
|
||||
break;
|
||||
memcpy(pathbuf, path, dirlen);
|
||||
memcpy(pathbuf + dirlen, "/", 2);
|
||||
cp = strchr(pathbuf + len + 1, '/');
|
||||
strbuf_reset(&pathbuf);
|
||||
strbuf_add(&pathbuf, path, dirlen);
|
||||
strbuf_addch(&pathbuf, '/');
|
||||
cp = strchr(pathbuf.buf + len + 1, '/');
|
||||
strcpy(cp + 1, GITATTRIBUTES_FILE);
|
||||
elem = read_attr(pathbuf, 0);
|
||||
elem = read_attr(pathbuf.buf, 0);
|
||||
*cp = '\0';
|
||||
elem->origin = strdup(pathbuf);
|
||||
elem->origin = strdup(pathbuf.buf);
|
||||
elem->prev = attr_stack;
|
||||
attr_stack = elem;
|
||||
debug_push(elem);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char * const builtin_add_usage[] = {
|
||||
"git-add [options] [--] <filepattern>...",
|
||||
"git add [options] [--] <filepattern>...",
|
||||
NULL
|
||||
};
|
||||
static int patch_interactive = 0, add_interactive = 0;
|
||||
@@ -140,9 +140,8 @@ static void refresh(int verbose, const char **pathspec)
|
||||
for (specs = 0; pathspec[specs]; specs++)
|
||||
/* nothing */;
|
||||
seen = xcalloc(specs, 1);
|
||||
if (read_cache() < 0)
|
||||
die("index file corrupt");
|
||||
refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen);
|
||||
refresh_index(&the_index, verbose ? REFRESH_SAY_CHANGED : REFRESH_QUIET,
|
||||
pathspec, seen);
|
||||
for (i = 0; i < specs; i++) {
|
||||
if (!seen[i])
|
||||
die("pathspec '%s' did not match any files", pathspec[i]);
|
||||
@@ -192,7 +191,7 @@ static const char ignore_error[] =
|
||||
"The following paths are ignored by one of your .gitignore files:\n";
|
||||
|
||||
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
|
||||
static int ignore_add_errors;
|
||||
static int ignore_add_errors, addremove;
|
||||
|
||||
static struct option builtin_add_options[] = {
|
||||
OPT__DRY_RUN(&show_only),
|
||||
@@ -202,6 +201,7 @@ static struct option builtin_add_options[] = {
|
||||
OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
|
||||
OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
|
||||
OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
|
||||
OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
|
||||
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
|
||||
OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
|
||||
OPT_END(),
|
||||
@@ -216,13 +216,36 @@ static int add_config(const char *var, const char *value, void *cb)
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static int add_files(struct dir_struct *dir, int flags)
|
||||
{
|
||||
int i, exit_status = 0;
|
||||
|
||||
if (dir->ignored_nr) {
|
||||
fprintf(stderr, ignore_error);
|
||||
for (i = 0; i < dir->ignored_nr; i++)
|
||||
fprintf(stderr, "%s\n", dir->ignored[i]->name);
|
||||
fprintf(stderr, "Use -f if you really want to add them.\n");
|
||||
die("no files added");
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->nr; i++)
|
||||
if (add_file_to_cache(dir->entries[i]->name, flags)) {
|
||||
if (!ignore_add_errors)
|
||||
die("adding files failed");
|
||||
exit_status = 1;
|
||||
}
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int exit_status = 0;
|
||||
int i, newfd;
|
||||
int newfd;
|
||||
const char **pathspec;
|
||||
struct dir_struct dir;
|
||||
int flags;
|
||||
int add_new_files;
|
||||
int require_pathspec;
|
||||
|
||||
argc = parse_options(argc, argv, builtin_add_options,
|
||||
builtin_add_usage, 0);
|
||||
@@ -233,53 +256,51 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
|
||||
git_config(add_config, NULL);
|
||||
|
||||
if (addremove && take_worktree_changes)
|
||||
die("-A and -u are mutually incompatible");
|
||||
if (addremove && !argc) {
|
||||
static const char *here[2] = { ".", NULL };
|
||||
argc = 1;
|
||||
argv = here;
|
||||
}
|
||||
|
||||
add_new_files = !take_worktree_changes && !refresh_only;
|
||||
require_pathspec = !take_worktree_changes;
|
||||
|
||||
newfd = hold_locked_index(&lock_file, 1);
|
||||
|
||||
flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
|
||||
(show_only ? ADD_CACHE_PRETEND : 0) |
|
||||
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));
|
||||
|
||||
if (take_worktree_changes) {
|
||||
const char **pathspec;
|
||||
if (read_cache() < 0)
|
||||
die("index file corrupt");
|
||||
pathspec = get_pathspec(prefix, argv);
|
||||
exit_status = add_files_to_cache(prefix, pathspec, flags);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
if (require_pathspec && argc == 0) {
|
||||
fprintf(stderr, "Nothing specified, nothing added.\n");
|
||||
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
|
||||
return 0;
|
||||
}
|
||||
pathspec = get_pathspec(prefix, argv);
|
||||
|
||||
/*
|
||||
* If we are adding new files, we need to scan the working
|
||||
* tree to find the ones that match pathspecs; this needs
|
||||
* to be done before we read the index.
|
||||
*/
|
||||
if (add_new_files)
|
||||
fill_directory(&dir, pathspec, ignored_too);
|
||||
|
||||
if (read_cache() < 0)
|
||||
die("index file corrupt");
|
||||
|
||||
if (refresh_only) {
|
||||
refresh(verbose, pathspec);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
fill_directory(&dir, pathspec, ignored_too);
|
||||
if (take_worktree_changes || addremove)
|
||||
exit_status |= add_files_to_cache(prefix, pathspec, flags);
|
||||
|
||||
if (read_cache() < 0)
|
||||
die("index file corrupt");
|
||||
|
||||
if (dir.ignored_nr) {
|
||||
fprintf(stderr, ignore_error);
|
||||
for (i = 0; i < dir.ignored_nr; i++) {
|
||||
fprintf(stderr, "%s\n", dir.ignored[i]->name);
|
||||
}
|
||||
fprintf(stderr, "Use -f if you really want to add them.\n");
|
||||
die("no files added");
|
||||
}
|
||||
|
||||
for (i = 0; i < dir.nr; i++)
|
||||
if (add_file_to_cache(dir.entries[i]->name, flags)) {
|
||||
if (!ignore_add_errors)
|
||||
die("adding files failed");
|
||||
exit_status = 1;
|
||||
}
|
||||
if (add_new_files)
|
||||
exit_status |= add_files(&dir, flags);
|
||||
|
||||
finish:
|
||||
if (active_cache_changed) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "blob.h"
|
||||
#include "delta.h"
|
||||
#include "builtin.h"
|
||||
#include "path-list.h"
|
||||
#include "string-list.h"
|
||||
|
||||
/*
|
||||
* --check turns on checking that the working tree matches the
|
||||
@@ -46,7 +46,7 @@ static const char *fake_ancestor;
|
||||
static int line_termination = '\n';
|
||||
static unsigned long p_context = ULONG_MAX;
|
||||
static const char apply_usage[] =
|
||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
|
||||
"git apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
|
||||
|
||||
static enum ws_error_action {
|
||||
nowarn_ws_error,
|
||||
@@ -194,7 +194,7 @@ struct image {
|
||||
* the case where more than one patches touch the same file.
|
||||
*/
|
||||
|
||||
static struct path_list fn_table;
|
||||
static struct string_list fn_table;
|
||||
|
||||
static uint32_t hash_line(const char *cp, size_t len)
|
||||
{
|
||||
@@ -2250,12 +2250,12 @@ static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
|
||||
|
||||
static struct patch *in_fn_table(const char *name)
|
||||
{
|
||||
struct path_list_item *item;
|
||||
struct string_list_item *item;
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
item = path_list_lookup(name, &fn_table);
|
||||
item = string_list_lookup(name, &fn_table);
|
||||
if (item != NULL)
|
||||
return (struct patch *)item->util;
|
||||
|
||||
@@ -2264,7 +2264,7 @@ static struct patch *in_fn_table(const char *name)
|
||||
|
||||
static void add_to_fn_table(struct patch *patch)
|
||||
{
|
||||
struct path_list_item *item;
|
||||
struct string_list_item *item;
|
||||
|
||||
/*
|
||||
* Always add new_name unless patch is a deletion
|
||||
@@ -2272,7 +2272,7 @@ static void add_to_fn_table(struct patch *patch)
|
||||
* file creations and copies
|
||||
*/
|
||||
if (patch->new_name != NULL) {
|
||||
item = path_list_insert(patch->new_name, &fn_table);
|
||||
item = string_list_insert(patch->new_name, &fn_table);
|
||||
item->util = patch;
|
||||
}
|
||||
|
||||
@@ -2281,7 +2281,7 @@ static void add_to_fn_table(struct patch *patch)
|
||||
* later chunks shouldn't patch old names
|
||||
*/
|
||||
if ((patch->new_name == NULL) || (patch->is_rename)) {
|
||||
item = path_list_insert(patch->old_name, &fn_table);
|
||||
item = string_list_insert(patch->old_name, &fn_table);
|
||||
item->util = (struct patch *) -1;
|
||||
}
|
||||
}
|
||||
@@ -3051,7 +3051,7 @@ static int apply_patch(int fd, const char *filename, int options)
|
||||
int skipped_patch = 0;
|
||||
|
||||
/* FIXME - memory leak when using multiple patch files as inputs */
|
||||
memset(&fn_table, 0, sizeof(struct path_list));
|
||||
memset(&fn_table, 0, sizeof(struct string_list));
|
||||
strbuf_init(&buf, 0);
|
||||
patch_input_file = filename;
|
||||
read_patch_file(&buf, fd);
|
||||
|
||||
@@ -5,25 +5,8 @@
|
||||
#include "cache.h"
|
||||
#include "builtin.h"
|
||||
#include "archive.h"
|
||||
#include "commit.h"
|
||||
#include "tree-walk.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "pkt-line.h"
|
||||
#include "sideband.h"
|
||||
#include "attr.h"
|
||||
|
||||
static const char archive_usage[] = \
|
||||
"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
|
||||
|
||||
static struct archiver_desc
|
||||
{
|
||||
const char *name;
|
||||
write_archive_fn_t write_archive;
|
||||
parse_extra_args_fn_t parse_extra;
|
||||
} archivers[] = {
|
||||
{ "tar", write_tar_archive, NULL },
|
||||
{ "zip", write_zip_archive, parse_extra_zip_args },
|
||||
};
|
||||
|
||||
static int run_remote_archiver(const char *remote, int argc,
|
||||
const char **argv)
|
||||
@@ -32,7 +15,7 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
int fd[2], i, len, rv;
|
||||
struct child_process *conn;
|
||||
const char *exec = "git-upload-archive";
|
||||
int exec_at = 0;
|
||||
int exec_at = 0, exec_value_at = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
@@ -41,7 +24,14 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
die("multiple --exec specified");
|
||||
exec = arg + 7;
|
||||
exec_at = i;
|
||||
break;
|
||||
} else if (!strcmp(arg, "--exec")) {
|
||||
if (exec_at)
|
||||
die("multiple --exec specified");
|
||||
if (i + 1 >= argc)
|
||||
die("option --exec requires a value");
|
||||
exec = argv[i + 1];
|
||||
exec_at = i;
|
||||
exec_value_at = ++i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +39,7 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
conn = git_connect(fd, url, exec, 0);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (i == exec_at)
|
||||
if (i == exec_at || i == exec_value_at)
|
||||
continue;
|
||||
packet_write(fd[1], "argument %s\n", argv[i]);
|
||||
}
|
||||
@@ -79,132 +69,6 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
return !!rv;
|
||||
}
|
||||
|
||||
static int init_archiver(const char *name, struct archiver *ar)
|
||||
{
|
||||
int rv = -1, i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(archivers); i++) {
|
||||
if (!strcmp(name, archivers[i].name)) {
|
||||
memset(ar, 0, sizeof(*ar));
|
||||
ar->name = archivers[i].name;
|
||||
ar->write_archive = archivers[i].write_archive;
|
||||
ar->parse_extra = archivers[i].parse_extra;
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void parse_pathspec_arg(const char **pathspec, struct archiver_args *ar_args)
|
||||
{
|
||||
ar_args->pathspec = get_pathspec(ar_args->base, pathspec);
|
||||
}
|
||||
|
||||
void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
|
||||
const char *prefix)
|
||||
{
|
||||
const char *name = argv[0];
|
||||
const unsigned char *commit_sha1;
|
||||
time_t archive_time;
|
||||
struct tree *tree;
|
||||
const struct commit *commit;
|
||||
unsigned char sha1[20];
|
||||
|
||||
if (get_sha1(name, sha1))
|
||||
die("Not a valid object name");
|
||||
|
||||
commit = lookup_commit_reference_gently(sha1, 1);
|
||||
if (commit) {
|
||||
commit_sha1 = commit->object.sha1;
|
||||
archive_time = commit->date;
|
||||
} else {
|
||||
commit_sha1 = NULL;
|
||||
archive_time = time(NULL);
|
||||
}
|
||||
|
||||
tree = parse_tree_indirect(sha1);
|
||||
if (tree == NULL)
|
||||
die("not a tree object");
|
||||
|
||||
if (prefix) {
|
||||
unsigned char tree_sha1[20];
|
||||
unsigned int mode;
|
||||
int err;
|
||||
|
||||
err = get_tree_entry(tree->object.sha1, prefix,
|
||||
tree_sha1, &mode);
|
||||
if (err || !S_ISDIR(mode))
|
||||
die("current working directory is untracked");
|
||||
|
||||
tree = parse_tree_indirect(tree_sha1);
|
||||
}
|
||||
ar_args->tree = tree;
|
||||
ar_args->commit_sha1 = commit_sha1;
|
||||
ar_args->commit = commit;
|
||||
ar_args->time = archive_time;
|
||||
}
|
||||
|
||||
int parse_archive_args(int argc, const char **argv, struct archiver *ar)
|
||||
{
|
||||
const char *extra_argv[MAX_EXTRA_ARGS];
|
||||
int extra_argc = 0;
|
||||
const char *format = "tar";
|
||||
const char *base = "";
|
||||
int verbose = 0;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
if (!strcmp(arg, "--list") || !strcmp(arg, "-l")) {
|
||||
for (i = 0; i < ARRAY_SIZE(archivers); i++)
|
||||
printf("%s\n", archivers[i].name);
|
||||
exit(0);
|
||||
}
|
||||
if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) {
|
||||
verbose = 1;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--format=")) {
|
||||
format = arg + 9;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--prefix=")) {
|
||||
base = arg + 9;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--")) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (arg[0] == '-') {
|
||||
if (extra_argc > MAX_EXTRA_ARGS - 1)
|
||||
die("Too many extra options");
|
||||
extra_argv[extra_argc++] = arg;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* We need at least one parameter -- tree-ish */
|
||||
if (argc - 1 < i)
|
||||
usage(archive_usage);
|
||||
if (init_archiver(format, ar) < 0)
|
||||
die("Unknown archive format '%s'", format);
|
||||
|
||||
if (extra_argc) {
|
||||
if (!ar->parse_extra)
|
||||
die("'%s' format does not handle %s",
|
||||
ar->name, extra_argv[0]);
|
||||
ar->args.extra = ar->parse_extra(extra_argc, extra_argv);
|
||||
}
|
||||
ar->args.verbose = verbose;
|
||||
ar->args.base = base;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static const char *extract_remote_arg(int *ac, const char **av)
|
||||
{
|
||||
int ix, iy, cnt = *ac;
|
||||
@@ -221,6 +85,13 @@ static const char *extract_remote_arg(int *ac, const char **av)
|
||||
die("Multiple --remote specified");
|
||||
remote = arg + 9;
|
||||
continue;
|
||||
} else if (!strcmp(arg, "--remote")) {
|
||||
if (remote)
|
||||
die("Multiple --remote specified");
|
||||
if (++ix >= cnt)
|
||||
die("option --remote requires a value");
|
||||
remote = av[ix];
|
||||
continue;
|
||||
}
|
||||
if (arg[0] != '-')
|
||||
no_more_options = 1;
|
||||
@@ -238,8 +109,6 @@ static const char *extract_remote_arg(int *ac, const char **av)
|
||||
|
||||
int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct archiver ar;
|
||||
int tree_idx;
|
||||
const char *remote = NULL;
|
||||
|
||||
remote = extract_remote_arg(&argc, argv);
|
||||
@@ -248,14 +117,5 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
|
||||
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
|
||||
|
||||
memset(&ar, 0, sizeof(ar));
|
||||
tree_idx = parse_archive_args(argc, argv, &ar);
|
||||
if (prefix == NULL)
|
||||
prefix = setup_git_directory();
|
||||
|
||||
argv += tree_idx;
|
||||
parse_treeish_arg(argv, &ar.args, prefix);
|
||||
parse_pathspec_arg(argv + 1, &ar.args);
|
||||
|
||||
return ar.write_archive(&ar.args);
|
||||
return write_archive(argc, argv, prefix, 1);
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
#include "quote.h"
|
||||
#include "xdiff-interface.h"
|
||||
#include "cache-tree.h"
|
||||
#include "path-list.h"
|
||||
#include "string-list.h"
|
||||
#include "mailmap.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static char blame_usage[] = "git-blame [options] [rev-opts] [rev] [--] file";
|
||||
static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
|
||||
|
||||
static const char *blame_opt_usage[] = {
|
||||
blame_usage,
|
||||
@@ -40,7 +40,7 @@ static int blank_boundary;
|
||||
static int incremental;
|
||||
static int cmd_is_annotate;
|
||||
static int xdl_opts = XDF_NEED_MINIMAL;
|
||||
static struct path_list mailmap;
|
||||
static struct string_list mailmap;
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
@@ -153,6 +153,10 @@ struct blame_entry {
|
||||
*/
|
||||
char guilty;
|
||||
|
||||
/* true if the entry has been scanned for copies in the current parent
|
||||
*/
|
||||
char scanned;
|
||||
|
||||
/* the line number of the first line of this group in the
|
||||
* suspect's file; internally all line numbers are 0 based.
|
||||
*/
|
||||
@@ -1008,7 +1012,8 @@ 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 || !same_suspect(e->suspect, target))
|
||||
if (e->guilty || !same_suspect(e->suspect, target) ||
|
||||
ent_score(sb, e) < blame_move_score)
|
||||
continue;
|
||||
find_copy_in_blob(sb, e, parent, split, &file_p);
|
||||
if (split[1].suspect &&
|
||||
@@ -1033,6 +1038,7 @@ struct blame_list {
|
||||
*/
|
||||
static struct blame_list *setup_blame_list(struct scoreboard *sb,
|
||||
struct origin *target,
|
||||
int min_score,
|
||||
int *num_ents_p)
|
||||
{
|
||||
struct blame_entry *e;
|
||||
@@ -1040,18 +1046,32 @@ 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 && same_suspect(e->suspect, target))
|
||||
if (!e->scanned && !e->guilty &&
|
||||
same_suspect(e->suspect, target) &&
|
||||
min_score < ent_score(sb, e))
|
||||
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 && same_suspect(e->suspect, target))
|
||||
if (!e->scanned && !e->guilty &&
|
||||
same_suspect(e->suspect, target) &&
|
||||
min_score < ent_score(sb, e))
|
||||
blame_list[i++].ent = e;
|
||||
}
|
||||
*num_ents_p = num_ents;
|
||||
return blame_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the scanned status on all entries.
|
||||
*/
|
||||
static void reset_scanned_flag(struct scoreboard *sb)
|
||||
{
|
||||
struct blame_entry *e;
|
||||
for (e = sb->ent; e; e = e->next)
|
||||
e->scanned = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For lines target is suspected for, see if we can find code movement
|
||||
* across file boundary from the parent commit. porigin is the path
|
||||
@@ -1070,7 +1090,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
|
||||
struct blame_list *blame_list;
|
||||
int num_ents;
|
||||
|
||||
blame_list = setup_blame_list(sb, target, &num_ents);
|
||||
blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents);
|
||||
if (!blame_list)
|
||||
return 1; /* nothing remains for this target */
|
||||
|
||||
@@ -1144,18 +1164,21 @@ static int find_copy_in_parent(struct scoreboard *sb,
|
||||
split_blame(sb, split, blame_list[j].ent);
|
||||
made_progress = 1;
|
||||
}
|
||||
else
|
||||
blame_list[j].ent->scanned = 1;
|
||||
decref_split(split);
|
||||
}
|
||||
free(blame_list);
|
||||
|
||||
if (!made_progress)
|
||||
break;
|
||||
blame_list = setup_blame_list(sb, target, &num_ents);
|
||||
blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents);
|
||||
if (!blame_list) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
reset_scanned_flag(sb);
|
||||
diff_flush(&diff_opts);
|
||||
diff_tree_release_paths(&diff_opts);
|
||||
return retval;
|
||||
@@ -1903,7 +1926,7 @@ static void sanity_check_refcnt(struct scoreboard *sb)
|
||||
* Used for the command line parsing; check if the path exists
|
||||
* in the working tree.
|
||||
*/
|
||||
static int has_path_in_work_tree(const char *path)
|
||||
static int has_string_in_work_tree(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
return !lstat(path, &st);
|
||||
@@ -2367,14 +2390,14 @@ parse_done:
|
||||
if (argc < 2)
|
||||
usage_with_options(blame_opt_usage, options);
|
||||
path = add_prefix(prefix, argv[argc - 1]);
|
||||
if (argc == 3 && !has_path_in_work_tree(path)) { /* (2b) */
|
||||
if (argc == 3 && !has_string_in_work_tree(path)) { /* (2b) */
|
||||
path = add_prefix(prefix, argv[1]);
|
||||
argv[1] = argv[2];
|
||||
}
|
||||
argv[argc - 1] = "--";
|
||||
|
||||
setup_work_tree();
|
||||
if (!has_path_in_work_tree(path))
|
||||
if (!has_string_in_work_tree(path))
|
||||
die("cannot stat path %s: %s", path, strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
#include "remote.h"
|
||||
#include "parse-options.h"
|
||||
#include "branch.h"
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
|
||||
static const char * const builtin_branch_usage[] = {
|
||||
"git-branch [options] [-r | -a] [--merged | --no-merged]",
|
||||
"git-branch [options] [-l] [-f] <branchname> [<start-point>]",
|
||||
"git-branch [options] [-r] (-d | -D) <branchname>",
|
||||
"git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
|
||||
"git branch [options] [-r | -a] [--merged | --no-merged]",
|
||||
"git branch [options] [-l] [-f] <branchname> [<start-point>]",
|
||||
"git branch [options] [-r] (-d | -D) <branchname>",
|
||||
"git branch [options] (-m | -M) [<oldbranch>] <newbranch>",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define REF_UNKNOWN_TYPE 0x00
|
||||
#define REF_LOCAL_BRANCH 0x01
|
||||
#define REF_REMOTE_BRANCH 0x02
|
||||
#define REF_TAG 0x04
|
||||
|
||||
static const char *head;
|
||||
static unsigned char head_sha1[20];
|
||||
@@ -181,25 +181,21 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
struct ref_item {
|
||||
char *name;
|
||||
unsigned int kind;
|
||||
unsigned char sha1[20];
|
||||
struct commit *commit;
|
||||
};
|
||||
|
||||
struct ref_list {
|
||||
struct rev_info revs;
|
||||
int index, alloc, maxwidth;
|
||||
struct ref_item *list;
|
||||
struct commit_list *with_commit;
|
||||
int kinds;
|
||||
};
|
||||
|
||||
static int has_commit(const unsigned char *sha1, struct commit_list *with_commit)
|
||||
static int has_commit(struct commit *commit, struct commit_list *with_commit)
|
||||
{
|
||||
struct commit *commit;
|
||||
|
||||
if (!with_commit)
|
||||
return 1;
|
||||
commit = lookup_commit_reference_gently(sha1, 1);
|
||||
if (!commit)
|
||||
return 0;
|
||||
while (with_commit) {
|
||||
struct commit *other;
|
||||
|
||||
@@ -215,7 +211,8 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
|
||||
{
|
||||
struct ref_list *ref_list = (struct ref_list*)(cb_data);
|
||||
struct ref_item *newitem;
|
||||
int kind = REF_UNKNOWN_TYPE;
|
||||
struct commit *commit;
|
||||
int kind;
|
||||
int len;
|
||||
static struct commit_list branch;
|
||||
|
||||
@@ -226,13 +223,15 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
|
||||
} else if (!prefixcmp(refname, "refs/remotes/")) {
|
||||
kind = REF_REMOTE_BRANCH;
|
||||
refname += 13;
|
||||
} else if (!prefixcmp(refname, "refs/tags/")) {
|
||||
kind = REF_TAG;
|
||||
refname += 10;
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
|
||||
commit = lookup_commit_reference_gently(sha1, 1);
|
||||
if (!commit)
|
||||
return error("branch '%s' does not point at a commit", refname);
|
||||
|
||||
/* Filter with with_commit if specified */
|
||||
if (!has_commit(sha1, ref_list->with_commit))
|
||||
if (!has_commit(commit, ref_list->with_commit))
|
||||
return 0;
|
||||
|
||||
/* Don't add types the caller doesn't want */
|
||||
@@ -243,12 +242,8 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
|
||||
branch.item = lookup_commit_reference_gently(sha1, 1);
|
||||
if (!branch.item)
|
||||
die("Unable to lookup tip of branch %s", refname);
|
||||
if (merge_filter == SHOW_NOT_MERGED &&
|
||||
has_commit(merge_filter_ref, &branch))
|
||||
return 0;
|
||||
if (merge_filter == SHOW_MERGED &&
|
||||
!has_commit(merge_filter_ref, &branch))
|
||||
return 0;
|
||||
add_pending_object(&ref_list->revs,
|
||||
(struct object *)branch.item, refname);
|
||||
}
|
||||
|
||||
/* Resize buffer */
|
||||
@@ -262,7 +257,7 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
|
||||
newitem = &(ref_list->list[ref_list->index++]);
|
||||
newitem->name = xstrdup(refname);
|
||||
newitem->kind = kind;
|
||||
hashcpy(newitem->sha1, sha1);
|
||||
newitem->commit = commit;
|
||||
len = strlen(newitem->name);
|
||||
if (len > ref_list->maxwidth)
|
||||
ref_list->maxwidth = len;
|
||||
@@ -309,7 +304,13 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
{
|
||||
char c;
|
||||
int color;
|
||||
struct commit *commit;
|
||||
struct commit *commit = item->commit;
|
||||
|
||||
if (merge_filter != NO_FILTER) {
|
||||
int is_merged = !!(item->commit->object.flags & UNINTERESTING);
|
||||
if (is_merged != (merge_filter == SHOW_MERGED))
|
||||
return;
|
||||
}
|
||||
|
||||
switch (item->kind) {
|
||||
case REF_LOCAL_BRANCH:
|
||||
@@ -337,7 +338,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
strbuf_init(&subject, 0);
|
||||
stat[0] = '\0';
|
||||
|
||||
commit = lookup_commit(item->sha1);
|
||||
commit = item->commit;
|
||||
if (commit && !parse_commit(commit)) {
|
||||
pretty_print_commit(CMIT_FMT_ONELINE, commit,
|
||||
&subject, 0, NULL, NULL, 0, 0);
|
||||
@@ -350,7 +351,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
|
||||
maxwidth, item->name,
|
||||
branch_get_color(COLOR_BRANCH_RESET),
|
||||
find_unique_abbrev(item->sha1, abbrev),
|
||||
find_unique_abbrev(item->commit->object.sha1, abbrev),
|
||||
stat, sub);
|
||||
strbuf_release(&subject);
|
||||
} else {
|
||||
@@ -363,22 +364,34 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
|
||||
{
|
||||
int i;
|
||||
struct ref_list ref_list;
|
||||
struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);
|
||||
|
||||
memset(&ref_list, 0, sizeof(ref_list));
|
||||
ref_list.kinds = kinds;
|
||||
ref_list.with_commit = with_commit;
|
||||
if (merge_filter != NO_FILTER)
|
||||
init_revisions(&ref_list.revs, NULL);
|
||||
for_each_ref(append_ref, &ref_list);
|
||||
if (merge_filter != NO_FILTER) {
|
||||
struct commit *filter;
|
||||
filter = lookup_commit_reference_gently(merge_filter_ref, 0);
|
||||
filter->object.flags |= UNINTERESTING;
|
||||
add_pending_object(&ref_list.revs,
|
||||
(struct object *) filter, "");
|
||||
ref_list.revs.limited = 1;
|
||||
prepare_revision_walk(&ref_list.revs);
|
||||
}
|
||||
|
||||
qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
|
||||
|
||||
detached = (detached && (kinds & REF_LOCAL_BRANCH));
|
||||
if (detached && has_commit(head_sha1, with_commit)) {
|
||||
if (detached && head_commit && has_commit(head_commit, with_commit)) {
|
||||
struct ref_item item;
|
||||
item.name = xstrdup("(no branch)");
|
||||
item.kind = REF_LOCAL_BRANCH;
|
||||
hashcpy(item.sha1, head_sha1);
|
||||
item.commit = head_commit;
|
||||
if (strlen(item.name) > ref_list.maxwidth)
|
||||
ref_list.maxwidth = strlen(item.name);
|
||||
ref_list.maxwidth = strlen(item.name);
|
||||
print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
|
||||
free(item.name);
|
||||
}
|
||||
|
||||
@@ -202,8 +202,8 @@ static int batch_objects(int print_contents)
|
||||
}
|
||||
|
||||
static const char * const cat_file_usage[] = {
|
||||
"git-cat-file [-t|-s|-e|-p|<type>] <sha1>",
|
||||
"git-cat-file [--batch|--batch-check] < <list_of_sha1s>",
|
||||
"git cat-file [-t|-s|-e|-p|<type>] <sha1>",
|
||||
"git cat-file [--batch|--batch-check] < <list_of_sha1s>",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "quote.h"
|
||||
|
||||
static const char check_attr_usage[] =
|
||||
"git-check-attr attr... [--] pathname...";
|
||||
"git check-attr attr... [--] pathname...";
|
||||
|
||||
int cmd_check_attr(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
|
||||
@@ -154,7 +154,7 @@ static void checkout_all(const char *prefix, int prefix_length)
|
||||
}
|
||||
|
||||
static const char checkout_cache_usage[] =
|
||||
"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
|
||||
"git checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
|
||||
|
||||
static struct lock_file lock_file;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
|
||||
}
|
||||
|
||||
static int update_some(const unsigned char *sha1, const char *base, int baselen,
|
||||
const char *pathname, unsigned mode, int stage)
|
||||
const char *pathname, unsigned mode, int stage, void *context)
|
||||
{
|
||||
int len;
|
||||
struct cache_entry *ce;
|
||||
@@ -67,7 +67,7 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
|
||||
|
||||
static int read_tree_some(struct tree *tree, const char **pathspec)
|
||||
{
|
||||
read_tree_recursive(tree, "", 0, 0, pathspec, update_some);
|
||||
read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL);
|
||||
|
||||
/* update the index with the given tree's info
|
||||
* for all args, expanding wildcards, and exit
|
||||
@@ -430,6 +430,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
||||
OPT_BOOLEAN('m', NULL, &opts.merge, "merge"),
|
||||
OPT_END(),
|
||||
};
|
||||
int has_dash_dash;
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
memset(&new, 0, sizeof(new));
|
||||
@@ -438,12 +439,57 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
||||
|
||||
opts.track = git_branch_track;
|
||||
|
||||
argc = parse_options(argc, argv, options, checkout_usage, 0);
|
||||
argc = parse_options(argc, argv, options, checkout_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
|
||||
if (!opts.new_branch && (opts.track != git_branch_track))
|
||||
die("git checkout: --track and --no-track require -b");
|
||||
|
||||
if (opts.force && opts.merge)
|
||||
die("git checkout: -f and -m are incompatible");
|
||||
|
||||
/*
|
||||
* case 1: git checkout <ref> -- [<paths>]
|
||||
*
|
||||
* <ref> must be a valid tree, everything after the '--' must be
|
||||
* a path.
|
||||
*
|
||||
* case 2: git checkout -- [<paths>]
|
||||
*
|
||||
* everything after the '--' must be paths.
|
||||
*
|
||||
* case 3: git checkout <something> [<paths>]
|
||||
*
|
||||
* With no paths, if <something> is a commit, that is to
|
||||
* switch to the branch or detach HEAD at it.
|
||||
*
|
||||
* Otherwise <something> shall not be ambiguous.
|
||||
* - If it's *only* a reference, treat it like case (1).
|
||||
* - If it's only a path, treat it like case (2).
|
||||
* - else: fail.
|
||||
*
|
||||
*/
|
||||
if (argc) {
|
||||
if (!strcmp(argv[0], "--")) { /* case (2) */
|
||||
argv++;
|
||||
argc--;
|
||||
goto no_reference;
|
||||
}
|
||||
|
||||
arg = argv[0];
|
||||
if (get_sha1(arg, rev))
|
||||
;
|
||||
else if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
|
||||
has_dash_dash = (argc > 1) && !strcmp(argv[1], "--");
|
||||
|
||||
if (get_sha1(arg, rev)) {
|
||||
if (has_dash_dash) /* case (1) */
|
||||
die("invalid reference: %s", arg);
|
||||
goto no_reference; /* case (3 -> 2) */
|
||||
}
|
||||
|
||||
/* we can't end up being in (2) anymore, eat the argument */
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
|
||||
new.name = arg;
|
||||
setup_branch_path(&new);
|
||||
if (resolve_ref(new.path, rev, 1, NULL))
|
||||
@@ -452,25 +498,28 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
||||
new.path = NULL;
|
||||
parse_commit(new.commit);
|
||||
source_tree = new.commit->tree;
|
||||
argv++;
|
||||
argc--;
|
||||
} else if ((source_tree = parse_tree_indirect(rev))) {
|
||||
} else
|
||||
source_tree = parse_tree_indirect(rev);
|
||||
|
||||
if (!source_tree) /* case (1): want a tree */
|
||||
die("reference is not a tree: %s", arg);
|
||||
if (!has_dash_dash) {/* case (3 -> 1) */
|
||||
/*
|
||||
* Do not complain the most common case
|
||||
* git checkout branch
|
||||
* even if there happen to be a file called 'branch';
|
||||
* it would be extremely annoying.
|
||||
*/
|
||||
if (argc)
|
||||
verify_non_filename(NULL, arg);
|
||||
}
|
||||
else {
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc && !strcmp(argv[0], "--")) {
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (!opts.new_branch && (opts.track != git_branch_track))
|
||||
die("git checkout: --track and --no-track require -b");
|
||||
|
||||
if (opts.force && opts.merge)
|
||||
die("git checkout: -f and -m are incompatible");
|
||||
|
||||
no_reference:
|
||||
if (argc) {
|
||||
const char **pathspec = get_pathspec(prefix, argv);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
static int force = -1; /* unset */
|
||||
|
||||
static const char *const builtin_clean_usage[] = {
|
||||
"git-clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
|
||||
"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*
|
||||
*/
|
||||
static const char * const builtin_clone_usage[] = {
|
||||
"git-clone [options] [--] <repo> [<dir>]",
|
||||
"git clone [options] [--] <repo> [<dir>]",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -95,35 +95,38 @@ static char *get_repo_path(const char *repo, int *is_bundle)
|
||||
|
||||
static char *guess_dir_name(const char *repo, int is_bundle)
|
||||
{
|
||||
const char *p, *start, *end, *limit;
|
||||
int after_slash_or_colon;
|
||||
const char *end = repo + strlen(repo), *start;
|
||||
|
||||
/* Guess dir name from repository: strip trailing '/',
|
||||
* strip trailing '[:/]*.{git,bundle}', strip leading '.*[/:]'. */
|
||||
/*
|
||||
* Strip trailing slashes and /.git
|
||||
*/
|
||||
while (repo < end && is_dir_sep(end[-1]))
|
||||
end--;
|
||||
if (end - repo > 5 && is_dir_sep(end[-5]) &&
|
||||
!strncmp(end - 4, ".git", 4)) {
|
||||
end -= 5;
|
||||
while (repo < end && is_dir_sep(end[-1]))
|
||||
end--;
|
||||
}
|
||||
|
||||
after_slash_or_colon = 1;
|
||||
limit = repo + strlen(repo);
|
||||
start = repo;
|
||||
end = limit;
|
||||
for (p = repo; p < limit; p++) {
|
||||
const char *prefix = is_bundle ? ".bundle" : ".git";
|
||||
if (!prefixcmp(p, prefix)) {
|
||||
if (!after_slash_or_colon)
|
||||
end = p;
|
||||
p += strlen(prefix) - 1;
|
||||
} else if (!prefixcmp(p, ".bundle")) {
|
||||
if (!after_slash_or_colon)
|
||||
end = p;
|
||||
p += 7;
|
||||
} else if (is_dir_sep(*p) || *p == ':') {
|
||||
if (end == limit)
|
||||
end = p;
|
||||
after_slash_or_colon = 1;
|
||||
} else if (after_slash_or_colon) {
|
||||
start = p;
|
||||
end = limit;
|
||||
after_slash_or_colon = 0;
|
||||
}
|
||||
/*
|
||||
* Find last component, but be prepared that repo could have
|
||||
* the form "remote.example.com:foo.git", i.e. no slash
|
||||
* in the directory part.
|
||||
*/
|
||||
start = end;
|
||||
while (repo < start && !is_dir_sep(start[-1]) && start[-1] != ':')
|
||||
start--;
|
||||
|
||||
/*
|
||||
* Strip .{bundle,git}.
|
||||
*/
|
||||
if (is_bundle) {
|
||||
if (end - start > 7 && !strncmp(end - 7, ".bundle", 7))
|
||||
end -= 7;
|
||||
} else {
|
||||
if (end - start > 4 && !strncmp(end - 4, ".git", 4))
|
||||
end -= 4;
|
||||
}
|
||||
|
||||
return xstrndup(start, end - start);
|
||||
@@ -477,6 +480,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
if (option_quiet)
|
||||
transport->verbose = -1;
|
||||
|
||||
if (option_upload_pack)
|
||||
transport_set_option(transport, TRANS_OPT_UPLOADPACK,
|
||||
option_upload_pack);
|
||||
|
||||
refs = transport_get_remote_refs(transport);
|
||||
transport_fetch_refs(transport, refs);
|
||||
}
|
||||
|
||||
@@ -21,17 +21,17 @@
|
||||
#include "strbuf.h"
|
||||
#include "utf8.h"
|
||||
#include "parse-options.h"
|
||||
#include "path-list.h"
|
||||
#include "string-list.h"
|
||||
#include "rerere.h"
|
||||
#include "unpack-trees.h"
|
||||
|
||||
static const char * const builtin_commit_usage[] = {
|
||||
"git-commit [options] [--] <filepattern>...",
|
||||
"git commit [options] [--] <filepattern>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * const builtin_status_usage[] = {
|
||||
"git-status [options] [--] <filepattern>...",
|
||||
"git status [options] [--] <filepattern>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -68,8 +68,8 @@ static enum {
|
||||
static char *cleanup_arg;
|
||||
|
||||
static int use_editor = 1, initial_commit, in_merge;
|
||||
const char *only_include_assumed;
|
||||
struct strbuf message;
|
||||
static const char *only_include_assumed;
|
||||
static struct strbuf message;
|
||||
|
||||
static int opt_parse_m(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
@@ -78,8 +78,7 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
|
||||
strbuf_setlen(buf, 0);
|
||||
else {
|
||||
strbuf_addstr(buf, arg);
|
||||
strbuf_addch(buf, '\n');
|
||||
strbuf_addch(buf, '\n');
|
||||
strbuf_addstr(buf, "\n\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -150,7 +149,7 @@ static int commit_index_files(void)
|
||||
* Take a union of paths in the index and the named tree (typically, "HEAD"),
|
||||
* and return the paths that match the given pattern in list.
|
||||
*/
|
||||
static int list_paths(struct path_list *list, const char *with_tree,
|
||||
static int list_paths(struct string_list *list, const char *with_tree,
|
||||
const char *prefix, const char **pattern)
|
||||
{
|
||||
int i;
|
||||
@@ -169,24 +168,24 @@ static int list_paths(struct path_list *list, const char *with_tree,
|
||||
continue;
|
||||
if (!pathspec_match(pattern, m, ce->name, 0))
|
||||
continue;
|
||||
path_list_insert(ce->name, list);
|
||||
string_list_insert(ce->name, list);
|
||||
}
|
||||
|
||||
return report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
|
||||
}
|
||||
|
||||
static void add_remove_files(struct path_list *list)
|
||||
static void add_remove_files(struct string_list *list)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < list->nr; i++) {
|
||||
struct stat st;
|
||||
struct path_list_item *p = &(list->items[i]);
|
||||
struct string_list_item *p = &(list->items[i]);
|
||||
|
||||
if (!lstat(p->path, &st)) {
|
||||
if (add_to_cache(p->path, &st, 0))
|
||||
if (!lstat(p->string, &st)) {
|
||||
if (add_to_cache(p->string, &st, 0))
|
||||
die("updating files failed");
|
||||
} else
|
||||
remove_file_from_cache(p->path);
|
||||
remove_file_from_cache(p->string);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +220,7 @@ static void create_base_index(void)
|
||||
static char *prepare_index(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int fd;
|
||||
struct path_list partial;
|
||||
struct string_list partial;
|
||||
const char **pathspec = NULL;
|
||||
|
||||
if (interactive) {
|
||||
@@ -305,7 +304,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
|
||||
die("cannot do a partial commit during a merge.");
|
||||
|
||||
memset(&partial, 0, sizeof(partial));
|
||||
partial.strdup_paths = 1;
|
||||
partial.strdup_strings = 1;
|
||||
if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
|
||||
exit(1);
|
||||
|
||||
@@ -647,7 +646,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
|
||||
char index[PATH_MAX];
|
||||
const char *env[2] = { index, NULL };
|
||||
snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
|
||||
launch_editor(git_path(commit_editmsg), NULL, env);
|
||||
if (launch_editor(git_path(commit_editmsg), NULL, env)) {
|
||||
fprintf(stderr,
|
||||
"Please supply the message using either -m or -F option.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!no_verify &&
|
||||
@@ -877,7 +880,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
|
||||
}
|
||||
}
|
||||
|
||||
int git_commit_config(const char *k, const char *v, void *cb)
|
||||
static int git_commit_config(const char *k, const char *v, void *cb)
|
||||
{
|
||||
if (!strcmp(k, "commit.template"))
|
||||
return git_config_string(&template_file, k, v);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "color.h"
|
||||
|
||||
static const char git_config_set_usage[] =
|
||||
"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--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 | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
|
||||
"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--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 | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
|
||||
|
||||
static char *key;
|
||||
static regex_t *key_regexp;
|
||||
@@ -145,7 +145,7 @@ free_strings:
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *normalize_value(const char *key, const char *value)
|
||||
static char *normalize_value(const char *key, const char *value)
|
||||
{
|
||||
char *normalized;
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
|
||||
}
|
||||
|
||||
static char const * const count_objects_usage[] = {
|
||||
"git-count-objects [-v]",
|
||||
"git count-objects [-v]",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#define MAX_TAGS (FLAG_BITS - 1)
|
||||
|
||||
static const char * const describe_usage[] = {
|
||||
"git-describe [options] <committish>*",
|
||||
"git describe [options] <committish>*",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ static int tags; /* But allow any tags if --tags is specified */
|
||||
static int longformat;
|
||||
static int abbrev = DEFAULT_ABBREV;
|
||||
static int max_candidates = 10;
|
||||
const char *pattern = NULL;
|
||||
static const char *pattern;
|
||||
static int always;
|
||||
|
||||
struct commit_name {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#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] [<common diff options>] [<path>...]"
|
||||
COMMON_DIFF_OPTIONS_HELP;
|
||||
|
||||
int cmd_diff_files(int argc, const char **argv, const char *prefix)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "builtin.h"
|
||||
|
||||
static const char diff_cache_usage[] =
|
||||
"git-diff-index [-m] [--cached] "
|
||||
"git diff-index [-m] [--cached] "
|
||||
"[<common diff options>] <tree-ish> [<path>...]"
|
||||
COMMON_DIFF_OPTIONS_HELP;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ static int diff_tree_stdin(char *line)
|
||||
}
|
||||
|
||||
static const char diff_tree_usage[] =
|
||||
"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
|
||||
"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
|
||||
"[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
|
||||
" -r diff recursively\n"
|
||||
" --root include the initial commit as diff against /dev/null\n"
|
||||
|
||||
@@ -21,7 +21,7 @@ struct blobinfo {
|
||||
};
|
||||
|
||||
static const char builtin_diff_usage[] =
|
||||
"git-diff <options> <rev>{0,2} -- <path>*";
|
||||
"git diff <options> <rev>{0,2} -- <path>*";
|
||||
|
||||
static void stuff_change(struct diff_options *opt,
|
||||
unsigned old_mode, unsigned new_mode,
|
||||
@@ -296,7 +296,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
||||
* If the user asked for our exit code then don't start a
|
||||
* pager or we would end up reporting its exit code instead.
|
||||
*/
|
||||
if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS))
|
||||
if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS) &&
|
||||
check_pager_config("diff") != 0)
|
||||
setup_pager();
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
#include "log-tree.h"
|
||||
#include "revision.h"
|
||||
#include "decorate.h"
|
||||
#include "path-list.h"
|
||||
#include "string-list.h"
|
||||
#include "utf8.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char *fast_export_usage[] = {
|
||||
"git-fast-export [rev-list-opts]",
|
||||
"git fast-export [rev-list-opts]",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -136,9 +136,18 @@ static void show_filemodify(struct diff_queue_struct *q,
|
||||
if (is_null_sha1(spec->sha1))
|
||||
printf("D %s\n", spec->path);
|
||||
else {
|
||||
struct object *object = lookup_object(spec->sha1);
|
||||
printf("M %06o :%d %s\n", spec->mode,
|
||||
get_object_mark(object), spec->path);
|
||||
/*
|
||||
* Links refer to objects in another repositories;
|
||||
* output the SHA-1 verbatim.
|
||||
*/
|
||||
if (S_ISGITLINK(spec->mode))
|
||||
printf("M %06o %s %s\n", spec->mode,
|
||||
sha1_to_hex(spec->sha1), spec->path);
|
||||
else {
|
||||
struct object *object = lookup_object(spec->sha1);
|
||||
printf("M %06o :%d %s\n", spec->mode,
|
||||
get_object_mark(object), spec->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,8 +205,10 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
||||
diff_root_tree_sha1(commit->tree->object.sha1,
|
||||
"", &rev->diffopt);
|
||||
|
||||
/* Export the referenced blobs, and remember the marks. */
|
||||
for (i = 0; i < diff_queued_diff.nr; i++)
|
||||
handle_object(diff_queued_diff.queue[i]->two->sha1);
|
||||
if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
|
||||
handle_object(diff_queued_diff.queue[i]->two->sha1);
|
||||
|
||||
mark_next_object(&commit->object);
|
||||
if (!is_encoding_utf8(encoding))
|
||||
@@ -298,7 +309,7 @@ static void handle_tag(const char *name, struct tag *tag)
|
||||
}
|
||||
|
||||
static void get_tags_and_duplicates(struct object_array *pending,
|
||||
struct path_list *extra_refs)
|
||||
struct string_list *extra_refs)
|
||||
{
|
||||
struct tag *tag;
|
||||
int i;
|
||||
@@ -319,7 +330,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
|
||||
case OBJ_TAG:
|
||||
tag = (struct tag *)e->item;
|
||||
while (tag && tag->object.type == OBJ_TAG) {
|
||||
path_list_insert(full_name, extra_refs)->util = tag;
|
||||
string_list_insert(full_name, extra_refs)->util = tag;
|
||||
tag = (struct tag *)tag->tagged;
|
||||
}
|
||||
if (!tag)
|
||||
@@ -339,19 +350,19 @@ static void get_tags_and_duplicates(struct object_array *pending,
|
||||
}
|
||||
if (commit->util)
|
||||
/* more than one name for the same object */
|
||||
path_list_insert(full_name, extra_refs)->util = commit;
|
||||
string_list_insert(full_name, extra_refs)->util = commit;
|
||||
else
|
||||
commit->util = full_name;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tags_and_duplicates(struct path_list *extra_refs)
|
||||
static void handle_tags_and_duplicates(struct string_list *extra_refs)
|
||||
{
|
||||
struct commit *commit;
|
||||
int i;
|
||||
|
||||
for (i = extra_refs->nr - 1; i >= 0; i--) {
|
||||
const char *name = extra_refs->items[i].path;
|
||||
const char *name = extra_refs->items[i].string;
|
||||
struct object *object = extra_refs->items[i].util;
|
||||
switch (object->type) {
|
||||
case OBJ_TAG:
|
||||
@@ -434,7 +445,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct rev_info revs;
|
||||
struct object_array commits = { 0, 0, NULL };
|
||||
struct path_list extra_refs = { NULL, 0, 0, 0 };
|
||||
struct string_list extra_refs = { NULL, 0, 0, 0 };
|
||||
struct commit *commit;
|
||||
char *export_filename = NULL, *import_filename = NULL;
|
||||
struct option options[] = {
|
||||
|
||||
@@ -18,7 +18,7 @@ static struct fetch_pack_args args = {
|
||||
};
|
||||
|
||||
static const char fetch_pack_usage[] =
|
||||
"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
|
||||
"git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
|
||||
|
||||
#define COMPLETE (1U << 0)
|
||||
#define COMMON (1U << 1)
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
#include "refs.h"
|
||||
#include "commit.h"
|
||||
#include "builtin.h"
|
||||
#include "path-list.h"
|
||||
#include "string-list.h"
|
||||
#include "remote.h"
|
||||
#include "transport.h"
|
||||
#include "run-command.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char * const builtin_fetch_usage[] = {
|
||||
"git-fetch [options] [<repository> <refspec>...]",
|
||||
"git fetch [options] [<repository> <refspec>...]",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -465,8 +465,8 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
|
||||
static int add_existing(const char *refname, const unsigned char *sha1,
|
||||
int flag, void *cbdata)
|
||||
{
|
||||
struct path_list *list = (struct path_list *)cbdata;
|
||||
path_list_insert(refname, list);
|
||||
struct string_list *list = (struct string_list *)cbdata;
|
||||
string_list_insert(refname, list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -485,8 +485,8 @@ static void find_non_local_tags(struct transport *transport,
|
||||
struct ref **head,
|
||||
struct ref ***tail)
|
||||
{
|
||||
struct path_list existing_refs = { NULL, 0, 0, 0 };
|
||||
struct path_list new_refs = { NULL, 0, 0, 1 };
|
||||
struct string_list existing_refs = { NULL, 0, 0, 0 };
|
||||
struct string_list new_refs = { NULL, 0, 0, 1 };
|
||||
char *ref_name;
|
||||
int ref_name_len;
|
||||
const unsigned char *ref_sha1;
|
||||
@@ -515,11 +515,11 @@ static void find_non_local_tags(struct transport *transport,
|
||||
}
|
||||
}
|
||||
|
||||
if (!path_list_has_path(&existing_refs, ref_name) &&
|
||||
!path_list_has_path(&new_refs, ref_name) &&
|
||||
if (!string_list_has_string(&existing_refs, ref_name) &&
|
||||
!string_list_has_string(&new_refs, ref_name) &&
|
||||
(has_sha1_file(ref->old_sha1) ||
|
||||
will_fetch(head, ref->old_sha1))) {
|
||||
path_list_insert(ref_name, &new_refs);
|
||||
string_list_insert(ref_name, &new_refs);
|
||||
|
||||
rm = alloc_ref_from_str(ref_name);
|
||||
rm->peer_ref = alloc_ref_from_str(ref_name);
|
||||
@@ -530,8 +530,8 @@ static void find_non_local_tags(struct transport *transport,
|
||||
}
|
||||
free(ref_name);
|
||||
}
|
||||
path_list_clear(&existing_refs, 0);
|
||||
path_list_clear(&new_refs, 0);
|
||||
string_list_clear(&existing_refs, 0);
|
||||
string_list_clear(&new_refs, 0);
|
||||
}
|
||||
|
||||
static int do_fetch(struct transport *transport,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "tag.h"
|
||||
|
||||
static const char *fmt_merge_msg_usage =
|
||||
"git-fmt-merge-msg [--log] [--no-log] [--file <file>]";
|
||||
"git fmt-merge-msg [--log] [--no-log] [--file <file>]";
|
||||
|
||||
static int merge_summary;
|
||||
|
||||
|
||||
@@ -809,7 +809,7 @@ static struct ref_sort *default_sort(void)
|
||||
return sort;
|
||||
}
|
||||
|
||||
int opt_parse_sort(const struct option *opt, const char *arg, int unset)
|
||||
static int opt_parse_sort(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct ref_sort **sort_tail = opt->value;
|
||||
struct ref_sort *s;
|
||||
@@ -831,7 +831,7 @@ int opt_parse_sort(const struct option *opt, const char *arg, int unset)
|
||||
}
|
||||
|
||||
static char const * const for_each_ref_usage[] = {
|
||||
"git-for-each-ref [options] [<pattern>]",
|
||||
"git for-each-ref [options] [<pattern>]",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -377,6 +377,10 @@ static void fsck_dir(int i, char *path)
|
||||
if (de->d_name[0] != '.')
|
||||
break;
|
||||
continue;
|
||||
case 14:
|
||||
if (prefixcmp(de->d_name, "tmp_obj_"))
|
||||
break;
|
||||
continue;
|
||||
case 38:
|
||||
sprintf(name, "%02x", i);
|
||||
memcpy(name+2, de->d_name, len+1);
|
||||
@@ -539,7 +543,7 @@ static int fsck_cache_tree(struct cache_tree *it)
|
||||
}
|
||||
|
||||
static char const * const fsck_usage[] = {
|
||||
"git-fsck [options] [<object>...]",
|
||||
"git fsck [options] [<object>...]",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define FAILED_RUN "failed to run %s"
|
||||
|
||||
static const char * const builtin_gc_usage[] = {
|
||||
"git-gc [options]",
|
||||
"git gc [options]",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -427,33 +427,35 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
|
||||
struct name_entry entry;
|
||||
char *down;
|
||||
int tn_len = strlen(tree_name);
|
||||
char *path_buf = xmalloc(PATH_MAX + tn_len + 100);
|
||||
struct strbuf pathbuf;
|
||||
|
||||
strbuf_init(&pathbuf, PATH_MAX + tn_len);
|
||||
|
||||
if (tn_len) {
|
||||
tn_len = sprintf(path_buf, "%s:", tree_name);
|
||||
down = path_buf + tn_len;
|
||||
strcat(down, base);
|
||||
strbuf_add(&pathbuf, tree_name, tn_len);
|
||||
strbuf_addch(&pathbuf, ':');
|
||||
tn_len = pathbuf.len;
|
||||
}
|
||||
else {
|
||||
down = path_buf;
|
||||
strcpy(down, base);
|
||||
}
|
||||
len = strlen(path_buf);
|
||||
strbuf_addstr(&pathbuf, base);
|
||||
len = pathbuf.len;
|
||||
|
||||
while (tree_entry(tree, &entry)) {
|
||||
strcpy(path_buf + len, entry.path);
|
||||
int te_len = tree_entry_len(entry.path, entry.sha1);
|
||||
pathbuf.len = len;
|
||||
strbuf_add(&pathbuf, entry.path, te_len);
|
||||
|
||||
if (S_ISDIR(entry.mode))
|
||||
/* Match "abc/" against pathspec to
|
||||
* decide if we want to descend into "abc"
|
||||
* directory.
|
||||
*/
|
||||
strcpy(path_buf + len + tree_entry_len(entry.path, entry.sha1), "/");
|
||||
strbuf_addch(&pathbuf, '/');
|
||||
|
||||
down = pathbuf.buf + tn_len;
|
||||
if (!pathspec_matches(paths, down))
|
||||
;
|
||||
else if (S_ISREG(entry.mode))
|
||||
hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len);
|
||||
hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
|
||||
else if (S_ISDIR(entry.mode)) {
|
||||
enum object_type type;
|
||||
struct tree_desc sub;
|
||||
@@ -469,6 +471,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
strbuf_release(&pathbuf);
|
||||
return hit;
|
||||
}
|
||||
|
||||
@@ -495,7 +498,7 @@ static int grep_object(struct grep_opt *opt, const char **paths,
|
||||
}
|
||||
|
||||
static const char builtin_grep_usage[] =
|
||||
"git-grep <option>* <rev>* [-e] <pattern> [<path>...]";
|
||||
"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
|
||||
|
||||
static const char emsg_invalid_context_len[] =
|
||||
"%s: invalid context length argument";
|
||||
|
||||
@@ -354,7 +354,7 @@ static int guess_repository_type(const char *git_dir)
|
||||
}
|
||||
|
||||
static const char init_db_usage[] =
|
||||
"git-init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
|
||||
"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
|
||||
|
||||
/*
|
||||
* If you want to, you can share the DB area with any number of branches.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user