Permalink
...
Comparing changes
Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .
Open a pull request
Create a new pull request by comparing changes across two branches. If you need to, you can also .
Choose a Base Repository
git/git
AndyStricker/git
AsherBond/git
Fabiano-lr/git
Fafinou/git
GunioRobot/git
Ippei0209/git
KarthikNayak/git
LarsDietrich/git
LittleForker/git
MichaelBlume/git
MikeBrWade/git
NandoKstroNet/git
Natshah/git
QPhuong/git
SRabbelier/git
Sidnicious/git
Siorghlas/git
SiriusShiu/git
TortoiseGit/tgit
Willtech/git
aarumug/git
adymitruk/git
agiratech-mars/git
albertz/git
algal/git
alick/git
andersonfarias/git
artagnon/git
asmeurer/git
asoltys/git
astubbs/git
avar/git
bafain/git
bakotaco/git
baldrick/git
baoping/git
barrbrain/git
bbarnett/git
bdonlan/git
bigdawgmj/git
bigfeng12/git
bjorng/git
boboroshi/git
bonfil1/git
bruceyue/git
carlosmn/git
changwoo/git-l10n-ko
chapuni/git
chevy2dr56/git
chriscool/git
chui/git
cloLN/git
cortextual/git
cvanes/git
dansmith65/git
darconeous/git
davvid/git
dirker/git
divanorama/git
dm0-/git
draco003/git
drizzd/git
dylanetkin/git
edalbem/git
emk/git
ericherman/git
fabiensanglard/git
felipec/git
fizx/git
flichtenheld/git
flyingflo/git
frogonwheels/git
gaojijun/git
git-for-windows/git
git-l10n/git-po
githubxl2ut/git
gitster/git
gotgit/git-po-zh_CN
greco/git
hamhei/git
helarious/git
helmo/git
hemanth/git
herbertjk/git
hesskah/git
hvoigt/git
icefox/git
iliasbartolini/git
ilya-bobyr/git
inovex/git
iveqy/git
jaredwy/git
jaseemabid/git
jasongiggy/git
jaswope/git
jayjay90/git
jherland/git
jhonyto/git
jhs/git
jiangxin/git
jjuran/git
jmckaskill/git
jmil/git
jmurzy/git
joeo/fut
jonseymour/git
jpbarrette/git
jpsilvaj/git
judofyr/git
julesbowden/git
junkshow/git
justinpitts/git
kblees/git
kenshin1991/git
koush/git
kpruden/git
ktateish/git-doc-ja_JP
kzys/git
lexaurin/git
lht/git
liancheng/git-po-zh_CN
macmartine/git
magicant/git
maharajd/git
matthiasgoergens/git
mbanana/git
mhagger/git
mildred/git
mjg/git
modocache/git-po-ja
msys2/git
msysgit/git
muratmeran/git
ngujral1/git
nickmayer/git
nothingmuch/git
nperez/git
npero/git
nulltoken/git
nvie/git
nzhang/git
ohoff/git
omgwtfun/git
pclouds/git
peff/git
pepellou/git
peterjmag/git
phreaknerd/git
pinheadg/git
pookleblinky/git
qmx/git
queencity13/git
radjosh/git
rafaalves/git
ralfth/git-po-de
rashmi/git
rctay/git
richardcpeterson/git
robertpfeiffer/git
ruizhang331/git
samuelkadolph/git-keychain
samv/git
saper/git
schacon/git
scottj97/git
sgolovnya/git
sheepmaster/git
siyo/git
skshiro/git
sneakin/git
spang/git
sunny256/git
suryasingh/git
terzino/git
testerofgithub/git
tgummerer/git
theefer/git
thihy/git
thomas-moulard/git
tomster/git
toshi-kawanishi/git
trast/git
tstachl/git
tvogel/git
twitter/git
vaceletm/git
vfr-nl/git-po
vijairaj/seed-git
vivekp/git
vmg/git
vnwildman/git
weider/git
wereHamster/git
witsch/git
wpalmer/git
wsp/git
wujiangthu/git
yuvrajm/git
zcoder/git
Nothing to show
Choose a Head Repository
git/git
AndyStricker/git
AsherBond/git
Fabiano-lr/git
Fafinou/git
GunioRobot/git
Ippei0209/git
KarthikNayak/git
LarsDietrich/git
LittleForker/git
MichaelBlume/git
MikeBrWade/git
NandoKstroNet/git
Natshah/git
QPhuong/git
SRabbelier/git
Sidnicious/git
Siorghlas/git
SiriusShiu/git
TortoiseGit/tgit
Willtech/git
aarumug/git
adymitruk/git
agiratech-mars/git
albertz/git
algal/git
alick/git
andersonfarias/git
artagnon/git
asmeurer/git
asoltys/git
astubbs/git
avar/git
bafain/git
bakotaco/git
baldrick/git
baoping/git
barrbrain/git
bbarnett/git
bdonlan/git
bigdawgmj/git
bigfeng12/git
bjorng/git
boboroshi/git
bonfil1/git
bruceyue/git
carlosmn/git
changwoo/git-l10n-ko
chapuni/git
chevy2dr56/git
chriscool/git
chui/git
cloLN/git
cortextual/git
cvanes/git
dansmith65/git
darconeous/git
davvid/git
dirker/git
divanorama/git
dm0-/git
draco003/git
drizzd/git
dylanetkin/git
edalbem/git
emk/git
ericherman/git
fabiensanglard/git
felipec/git
fizx/git
flichtenheld/git
flyingflo/git
frogonwheels/git
gaojijun/git
git-for-windows/git
git-l10n/git-po
githubxl2ut/git
gitster/git
gotgit/git-po-zh_CN
greco/git
hamhei/git
helarious/git
helmo/git
hemanth/git
herbertjk/git
hesskah/git
hvoigt/git
icefox/git
iliasbartolini/git
ilya-bobyr/git
inovex/git
iveqy/git
jaredwy/git
jaseemabid/git
jasongiggy/git
jaswope/git
jayjay90/git
jherland/git
jhonyto/git
jhs/git
jiangxin/git
jjuran/git
jmckaskill/git
jmil/git
jmurzy/git
joeo/fut
jonseymour/git
jpbarrette/git
jpsilvaj/git
judofyr/git
julesbowden/git
junkshow/git
justinpitts/git
kblees/git
kenshin1991/git
koush/git
kpruden/git
ktateish/git-doc-ja_JP
kzys/git
lexaurin/git
lht/git
liancheng/git-po-zh_CN
macmartine/git
magicant/git
maharajd/git
matthiasgoergens/git
mbanana/git
mhagger/git
mildred/git
mjg/git
modocache/git-po-ja
msys2/git
msysgit/git
muratmeran/git
ngujral1/git
nickmayer/git
nothingmuch/git
nperez/git
npero/git
nulltoken/git
nvie/git
nzhang/git
ohoff/git
omgwtfun/git
pclouds/git
peff/git
pepellou/git
peterjmag/git
phreaknerd/git
pinheadg/git
pookleblinky/git
qmx/git
queencity13/git
radjosh/git
rafaalves/git
ralfth/git-po-de
rashmi/git
rctay/git
richardcpeterson/git
robertpfeiffer/git
ruizhang331/git
samuelkadolph/git-keychain
samv/git
saper/git
schacon/git
scottj97/git
sgolovnya/git
sheepmaster/git
siyo/git
skshiro/git
sneakin/git
spang/git
sunny256/git
suryasingh/git
terzino/git
testerofgithub/git
tgummerer/git
theefer/git
thihy/git
thomas-moulard/git
tomster/git
toshi-kawanishi/git
trast/git
tstachl/git
tvogel/git
twitter/git
vaceletm/git
vfr-nl/git-po
vijairaj/seed-git
vivekp/git
vmg/git
vnwildman/git
weider/git
wereHamster/git
witsch/git
wpalmer/git
wsp/git
wujiangthu/git
yuvrajm/git
zcoder/git
Nothing to show
35
contributors
This comparison is big! We’re only showing the most recent
250
commits
Commits on Aug 19, 2015
pclouds |
t7063: use --force-untracked-cache to speed up a bit
When in the middle of t7063, we are sure untracked cache is supported, so we can use --force-untracked-cache to skip the support detection phase and save a few seconds. It's also good that --force-untracked-cache is exercised in the test suite. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
f178136
|
||
dturner-tw |
untracked-cache: fix subdirectory handling
Previously, some calls lookup_untracked would pass a full path. But lookup_untracked assumes that the portion of the path up to and including to the untracked_cache_dir has been removed. So lookup_untracked would be looking in the untracked_cache for 'foo' for 'foo/bar' (instead of just looking for 'bar'). This would cause untracked cache corruption. Instead, treat_directory learns to track the base length of the parent directory, so that only the last path component is passed to lookup_untracked. Helped-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: David Turner <dturner@twopensource.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
2e5910f
|
||
pclouds |
untracked cache: fix entry invalidation
First, the current code in untracked_cache_invalidate_path() is wrong because it can only handle paths "a" or "a/b", not "a/b/c" because lookup_untracked() only looks for entries directly under the given directory. In the last case, it will look for the entry "b/c" in directory "a" instead. This means if you delete or add an entry in a subdirectory, untracked cache may become out of date because it does not invalidate properly. This is noticed by David Turner. The second problem is about invalidation inside a fully untracked/excluded directory. In this case we may have to invalidate back to root. See the comment block for detail. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
73f9145
|
||
pyokagan |
am --skip/--abort: merge HEAD/ORIG_HEAD tree into index
After running "git am --abort", and then running "git reset --hard", files that were not modified would still be re-checked out. This is because clean_index() in builtin/am.c mistakenly called the read_tree() function, which overwrites all entries in the index, including the stat info. "git am --skip" did not seem to have this issue because am_skip() called am_run(), which called refresh_cache() to update the stat info. However, there's still a performance penalty as the lack of stat info meant that refresh_cache() would have to scan all files for changes. Fix this by using unpack_trees() instead to merge the tree into the index, so that the stat info from the index is kept. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
3ecc704
|
||
Heiko Voigt |
submodule: implement a config API for lookup of .gitmodules values
In a superproject some commands need to interact with submodules. They need to query values from the .gitmodules file either from the worktree of from certain revisions. At the moment this is quite hard since a caller would need to read the .gitmodules file from the history and then parse the values. We want to provide an API for this so we have one place to get values from .gitmodules from any revision (including the worktree). The API is realized as a cache which allows us to lazily read .gitmodules configurations by commit into a runtime cache which can then be used to easily lookup values from it. Currently only the values for path or name are stored but it can be extended for any value needed. It is expected that .gitmodules files do not change often between commits. Thats why we lookup the .gitmodules sha1 from a commit and then either lookup an already parsed configuration or parse and cache an unknown one for each sha1. The cache is lazily build on demand for each requested commit. This cache can be used for all purposes which need knowledge about submodule configurations. Example use cases are: * Recursive submodule checkout needs to lookup a submodule name from its path when a submodule first appears. This needs be done before this configuration exists in the worktree. * The implementation of submodule support for 'git archive' needs to lookup the submodule name to generate the archive when given a revision that is not checked out. * 'git fetch' when given the --recurse-submodules=on-demand option (or configuration) needs to lookup submodule names by path from the database rather than reading from the worktree. For new submodule it needs to lookup the name from its path to allow cloning new submodules into the .git folder so they can be checked out without any network interaction when the user does a checkout of that revision. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
959b545
|
||
Heiko Voigt |
submodule: extract functions for config set and lookup
This is one step towards using the new configuration API. We just extract these functions to make replacing the actual code easier. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
0d9f282
|
||
Heiko Voigt |
submodule: use new config API for worktree configurations
We remove the extracted functions and directly parse into and read out of the cache. This allows us to have one unified way of accessing submodule configuration values specific to single submodules. Regardless whether we need to access a configuration from history or from the worktree. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
851e18c
|
||
Heiko Voigt |
submodule: allow erroneous values for the fetchRecurseSubmodules option
We should not die when reading the submodule config cache since the user might not be able to get out of that situation when the configuration is part of the history. We should handle this condition later when the value is about to be used. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
027771f
|
||
dborowitz |
Documentation/git-push.txt: document when --signed may fail
Like --atomic, --signed will fail if the server does not advertise the necessary capability. In addition, it requires gpg on the client side. Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
f9e0952
|
||
dborowitz |
Documentation/git-send-pack.txt: wrap long synopsis line
Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
a3fb31a
|
||
dborowitz |
Documentation/git-send-pack.txt: document --signed
Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
66697fe
|
||
dborowitz |
gitremote-helpers.txt: document pushcert option
Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
b9299a2
|
||
dborowitz |
transport: remove git_transport_options.push_cert
This field was set in transport_set_option, but never read in the push code. The push code basically ignores the smart_options field entirely, and derives its options from the flags arguments to the push* callbacks. Note that in git_transport_push there are already several args set from flags that have no corresponding field in git_transport_options; after this change, push_cert is just like those. Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
87c0d08
|
||
dborowitz |
config.c: rename git_config_maybe_bool_text and export it as git_pars…
…e_maybe_bool This helper function does not complain about the config variable but just silently reports failure to the caller. It is useful for callers that need to parse any string that could be boolean or other string (e.g. tristate yes/no/auto). Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
9a549d4
|
||
dborowitz |
builtin/send-pack.c: use parse_options API
The old option parsing code in this plumbing command predates this API, so option parsing was done more manually. Using the new API brings send-pack more in line with push, and accepts new variants like --no-* for negating options. Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
068c77a
|
||
dborowitz |
push: support signing pushes iff the server supports it
Add a new flag --sign=true (or --sign=false), which means the same thing as the original --signed (or --no-signed). Give it a third value --sign=if-asked to tell push and send-pack to send a push certificate if and only if the server advertised a push cert nonce. If not, warn the user that their push may not be as secure as they thought. Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
3026109
|
||
dborowitz |
push: add a config option push.gpgSign for default signed pushes
Signed-off-by: Dave Borowitz <dborowitz@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
68c757f
|
||
gitster |
Merge branch 'da/subtree-date-confusion' into maint
"git subtree" (in contrib/) depended on "git log" output to be stable, which was a no-no. Apply a workaround to force a particular date format. * da/subtree-date-confusion: contrib/subtree: ignore log.date configuration |
5a30374
|
||
gitster |
Merge branch 'jx/do-not-crash-receive-pack-wo-head' into maint
An attempt to delete a ref by pushing into a repositorywhose HEAD symbolic reference points at an unborn branch that cannot be created due to ref D/F conflict (e.g. refs/heads/a/b exists, HEAD points at refs/heads/a) failed. * jx/do-not-crash-receive-pack-wo-head: receive-pack: crash when checking with non-exist HEAD |
17850ef
|
||
gitster |
Merge branch 'db/send-pack-user-signingkey' into maint
The low-level "git send-pack" did not honor 'user.signingkey' configuration variable when sending a signed-push. * db/send-pack-user-signingkey: builtin/send-pack.c: respect user.signingkey |
7e7ce32
|
||
gitster |
Merge branch 'as/sparse-checkout-removal' into maint
"sparse checkout" misbehaved for a path that is excluded from the checkout when switching between branches that differ at the path. * as/sparse-checkout-removal: unpack-trees: don't update files with CE_WT_REMOVE set |
4f66e44
|
||
gitster |
Merge branch 'cb/uname-in-untracked' into maint
An experimental "untracked cache" feature used uname(2) in a slightly unportable way. * cb/uname-in-untracked: untracked: fix detection of uname(2) failure |
b083703
|
||
gitster |
Merge branch 'se/doc-checkout-ours-theirs' into maint
A "rebase" replays changes of the local branch on top of something else, as such they are placed in stage #3 and referred to as "theirs", while the changes in the new base, typically a foreign work, are placed in stage #2 and referred to as "ours". Clarify the "checkout --ours/--theirs". * se/doc-checkout-ours-theirs: checkout: document subtlety around --ours/--theirs |
204ea3c
|
||
gitster |
Merge branch 'ib/scripted-parse-opt-better-hint-string' into maint
The "rev-parse --parseopt" mode parsed the option specification and the argument hint in a strange way to allow '=' and other special characters in the option name while forbidding them from the argument hint. This made it impossible to define an option like "--pair <key>=<value>" with "pair=key=value" specification, which instead would have defined a "--pair=key <value>" option. * ib/scripted-parse-opt-better-hint-string: rev-parse --parseopt: allow [*=?!] in argument hints |
d3ac359
|
||
gitster |
Merge branch 'mh/fast-import-optimize-current-from' into maint
Often a fast-import stream builds a new commit on top of the previous commit it built, and it often unconditionally emits a "from" command to specify the first parent, which can be omitted in such a case. This caused fast-import to forget the tree of the previous commit and then re-read it from scratch, which was inefficient. Optimize for this common case. * mh/fast-import-optimize-current-from: fast-import: do less work when given "from" matches current branch head |
f9610bc
|
||
gitster |
Merge branch 'nd/export-worktree' into maint
Running an aliased command from a subdirectory when the .git thing in the working tree is a gitfile pointing elsewhere did not work. * nd/export-worktree: setup: set env $GIT_WORK_TREE when work tree is set, like $GIT_DIR |
25a294e
|
||
gitster |
Merge branch 'es/doc-clean-outdated-tools' into maint
* es/doc-clean-outdated-tools: Documentation/git-tools: retire manually-maintained list Documentation/git-tools: drop references to defunct tools Documentation/git-tools: fix item text formatting Documentation/git-tools: improve discoverability of Git wiki Documentation/git: drop outdated Cogito reference |
cacee08
|
||
gitster |
Merge branch 'kn/tag-doc-fix' into maint
* kn/tag-doc-fix: Documentation/tag: remove double occurance of "<pattern>" |
24493ff
|
||
gitster |
Merge branch 'sb/remove-unused-var-from-builtin-add' into maint
* sb/remove-unused-var-from-builtin-add: add: remove dead code |
223b55a
|
||
gitster |
Merge branch 'sb/parse-options-codeformat' into maint
* sb/parse-options-codeformat: parse-options: align curly braces for all options |
b994b9b
|
||
gitster |
Merge branch 'ta/docfix-index-format-tech' into maint
* ta/docfix-index-format-tech: typofix for index-format.txt |
91db009
|
||
gitster |
Start preparing for 2.5.1
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
552a736
|
||
gitster |
Merge branch 'mm/pull-upload-pack'
"git pull" in recent releases of Git has a regression in the code that allows custom path to the --upload-pack=<program>. This has been corrected. Note that this is irrelevant for 'master' with "git pull" rewritten in C. * mm/pull-upload-pack: pull.sh: quote $upload_pack when passing it to git-fetch |
d772def
|
||
gitster |
Merge branch 'sb/check-return-from-read-ref'
* sb/check-return-from-read-ref: transport-helper: die on errors reading refs. |
1d82ef5
|
||
gitster |
Merge branch 'ps/t1509-chroot-test-fixup'
t1509 test that requires a dedicated VM environment had some bitrot, which has been corrected. * ps/t1509-chroot-test-fixup: tests: fix cleanup after tests in t1509-root-worktree tests: fix broken && chains in t1509-root-worktree |
034603f
|
||
gitster |
Merge branch 'jk/test-with-x'
Running tests with the "-x" option to make them verbose had some unpleasant interactions with other features of the test suite. * jk/test-with-x: test-lib: disable trace when test is not verbose test-lib: turn off "-x" tracing during chain-lint check |
138014c
|
||
gitster |
Merge branch 'jk/negative-hiderefs'
A negative !ref entry in multi-value transfer.hideRefs configuration can be used to say "don't hide this one". * jk/negative-hiderefs: refs: support negative transfer.hideRefs docs/config.txt: reorder hideRefs config |
824a0be
|
||
gitster |
Merge branch 'jk/guess-repo-name-regression-fix'
"git clone $URL" in recent releases of Git contains a regression in the code that invents a new repository name incorrectly based on the $URL. This has been corrected. * jk/guess-repo-name-regression-fix: clone: use computed length in guess_dir_name clone: add tests for output directory |
8259da5
|
||
gitster |
Merge branch 'ps/guess-repo-name-at-root'
"git clone $URL", when cloning from a site whose sole purpose is to host a single repository (hence, no path after <scheme>://<site>/), tried to use the site name as the new repository name, but did not remove username or password when <site> part was of the form <user>@<pass>:<host>. The code is taught to redact these. * ps/guess-repo-name-at-root: clone: abort if no dir name could be guessed clone: do not use port number as dir name clone: do not include authentication data in guessed dir |
4bfab58
|
||
gitster |
Merge branch 'jc/finalize-temp-file'
Long overdue micro clean-up. * jc/finalize-temp-file: sha1_file.c: rename move_temp_to_file() to finalize_object_file() |
51a22ce
|
||
gitster |
Merge branch 'jk/git-path'
git_path() and mkpath() are handy helper functions but it is easy to misuse, as the callers need to be careful to keep the number of active results below 4. Their uses have been reduced. * jk/git-path: memoize common git-path "constant" files get_repo_path: refactor path-allocation find_hook: keep our own static buffer refs.c: remove_empty_directories can take a strbuf refs.c: avoid git_path assignment in lock_ref_sha1_basic refs.c: avoid repeated git_path calls in rename_tmp_log refs.c: simplify strbufs in reflog setup and writing path.c: drop git_path_submodule refs.c: remove extra git_path calls from read_loose_refs remote.c: drop extraneous local variable from migrate_file prefer mkpathdup to mkpath in assignments prefer git_pathdup to git_path in some possibly-dangerous cases add_to_alternates_file: don't add duplicate entries t5700: modernize style cache.h: complete set of git_path_submodule helpers cache.h: clarify documentation for git_path, et al |
8c9155e
|
||
gitster |
Merge branch 'tb/complete-rebase-i-edit-todo'
The command-line completion script (in contrib/) has been updated. * tb/complete-rebase-i-edit-todo: completion: offer '--edit-todo' during interactive rebase |
011710a
|
||
gitster |
Fourth batch for 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
8f8d0ec
|
||
gitster |
Sync with maint
* maint: Start preparing for 2.5.1 |
ff86faf
|
Commits on Aug 20, 2015
gitster |
ps_matched: xcalloc() takes nmemb and then element size
Even though multiplication is commutative, the order of arguments should be xcalloc(nmemb, size). ps_matched is an array of 1-byte element whose size is the same as the number of pathspec elements. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
8b54c23
|
||
szeder |
t3020: fix typo in test description
Signed-off-by: SZEDER Gábor <szeder@ira.uka.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
1269847
|
||
szeder |
config: restructure format_config() for better control flow
Commit 578625f (config: add '--name-only' option to list only variable names, 2015-08-10) modified format_config() such that it returned from the middle of the function when showing only keys, resulting in ugly code structure. Reorganize the if statements and dealing with the key-value delimiter to make the function easier to read. Signed-off-by: SZEDER Gábor <szeder@ira.uka.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
ebca2d4
|
||
peff |
format_config: don't init strbuf
It's unusual for a function which writes to a passed-in strbuf to call strbuf_init; that will throw away anything already there, leaking memory. In this case, there are exactly two callers; one relies on this initialization and the other passes in an already-initialized buffer. There's no leak, as the initialized buffer doesn't have anything in it. But let's bump the strbuf_init out to the one caller who needs it, making format_config more idiomatic. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
9f1429d
|
||
peff |
format_config: simplify buffer handling
When formatting a config value into a strbuf, we may end up stringifying it into a fixed-size buffer using sprintf, and then copying that buffer into the strbuf. We can eliminate the middle-man (and drop some calls to sprintf!) by writing directly to the strbuf. The reason it was written this way in the first place is that we need to know before writing the value whether to insert a delimiter. Instead of delaying the write of the value, we speculatively write the delimiter, and roll it back in the single case that cares. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
f225987
|
||
peff |
get_urlmatch: avoid useless strbuf write
We create a strbuf only to insert a single string, pass the resulting buffer to a function (which does not modify the string), and then free it. We can just pass the original string instead. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
a92330d
|
||
gitster |
log: rename "tweak" helpers
The revision walking API allows the callers to tweak its configuration at the last minute, immediately after all the revision and pathspec parameters are parsed from the command line but before the default actions are decided based on them, by defining a "tweak" callback function when calling setup_revisions(). Traditionally, this facility was used by "git show" to turn on the patch output "-p" by default when no diff output option (e.g. "--raw" or "-s" to squelch the output altogether) is given on the command line, and further give dense combined diffs "--cc" for merge commits when no option to countermand it (e.g. "-m" to show pairwise patches). Recently, "git log" started using the same facility, but we named the callback function "default_follow_tweak()", as if the only kind of tweaking we would want for "git log" will forever be limited to turning "--follow" on by default when told by a configuration variable. That was myopic. Rename it to more generic name "log_setup_revisions_tweak()", and match the one used by show "show_setup_revisions_tweak()". Signed-off-by: Junio C Hamano <gitster@pobox.com> |
b130c70
|
||
gitster |
log: when --cc is given, default to -p unless told otherwise
The "--cc" option to "git log" is clearly a request to show some sort of combined diff (be it --patch or --raw), but traditionally we required the command line to explicitly ask for "git log -p --cc". Teach the command line parser to treat a lone "--cc" as if the user specified "-p --cc". Formats that do ask for other forms of diff output, e.g. "log --raw --cc", are not overriden. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
c7eaf8b
|
||
gitster |
log: show merge commit when --cc is given
We defaulted to ignoring merge diffs because long long ago, in a galaxy far away, we didn't have a great way to show the diffs. The whole "--cc" option goes back to January '06 and commit d8f4790 ("diff-tree --cc: denser combined diff output for a merge commit"). And before that option - so for about 8 months - we had no good way to show the diffs of merges in a good dense way. So the whole "don't show diffs for merges by default" actually made a lot of sense originally, because our merge diffs were not very useful. And this was carried forward to this day. "git log --cc" still ignores merge commits, and you need to say "git log -m --cc" to view a sensible rendition of merge and non-merge commits, even with the previous change to make "--cc" imply "-p". Teach "git log" that "--cc" means the user wants to see interesting changes in merge commits by turning "-m" on. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
82dee41
|
Commits on Aug 21, 2015
andreas-schwab |
Documentation/config: fix inconsistent label on gc.*.reflogExpireUnre…
…achable Change <ref> to <pattern> in the description of gc.*.reflogExpireUnreachable, since that is what the text refers to. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
f04c690
|
||
Christian Couder |
trailer: ignore first line of message
When looking for the start of the trailers in the message we are passed, we should ignore the first line of the message. The reason is that if we are passed a patch or commit message then the first line should be the patch title. If we are passed only trailers we can expect that they start with an empty line that can be ignored too. This way we can properly process commit messages that have only one line with something that looks like a trailer, for example like "area of code: change we made". Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
dc5d553
|
||
szeder |
wt-status: move #include "pathspec.h" to the header
The declaration of 'struct wt_status' requires the declararion of 'struct pathspec'. Signed-off-by: SZEDER Gábor <szeder@ira.uka.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
7aa9b9b
|
Commits on Aug 23, 2015
oldsharp |
l10n: zh_CN: Update Git Glossary: SHA-1
It's quite common to see the term "SHA-1" remain untranslated in many l10n works. So update the "SHA-1" entry in Git glossary to match this behavior. Signed-off-by: Ray Chen <oldsharp@gmail.com> |
ee7589b
|
||
oldsharp |
l10n: zh_CN: Update Git Glossary: "dumb", "smart"
"dumb/smart HTTP protocol" are normally considered as phrases. Add "protocol" as a suffix after them makes more sense. Signed-off-by: Ray Chen <oldsharp@gmail.com> |
755c831
|
||
oldsharp |
l10n: zh_CN: Update Git Glossary: tag
Add verb form translation of tag. Signed-off-by: Ray Chen <oldsharp@gmail.com> |
933c015
|
||
oldsharp |
l10n: zh_CN: Update Git Glossary: fork
Remove "复刻" from translation option list of "fork", keeping "派生" as the only one. In Git context, by talking about the term "fork", one usually mean the procedure that divides a branch into two or more history lines. That is quite like the "fork" concept in programming, which split a process into two or more independent processes. On the other hand, "复刻" by itself means "copy" or "mirror". It is considered more suitable for describing the procedure like "fork a repository", which is common on public repository hosting services, such as GitHub. However, this is beyond the scope of core-Git. As a l10n work for core-Git, "复刻" should be removed here. There used to be another option - "分岔". Its a good idea to translate "fork point" as "分岔点". However, "派生点" is as good, too. So this option is finally discarded. Also fix a relevant translation issue which was introduced in `160fb2b`. Signed-off-by: Ray Chen <oldsharp@gmail.com> |
e397e7e
|
||
oldsharp |
l10n: zh_CN: Update Git Glossary: pickaxe
Translate the term "pickaxe" as "挖掘". Initially proposed by @louy2 . Signed-off-by: Ray Chen <oldsharp@gmail.com> |
12e5905
|
Commits on Aug 24, 2015
peff |
config: silence warnings for command names with invalid keys
When we are running the git command "foo", we may have to look up the config keys "pager.foo" and "alias.foo". These config schemes are mis-designed, as the command names can be anything, but the config syntax has some restrictions. For example: $ git foo_bar error: invalid key: pager.foo_bar error: invalid key: alias.foo_bar git: 'foo_bar' is not a git command. See 'git --help'. You cannot name an alias with an underscore. And if you have an external command with one, you cannot configure its pager. In the long run, we may develop a different config scheme for these features. But in the near term (and because we'll need to support the existing scheme indefinitely), we should at least squelch the error messages shown above. These errors come from git_config_parse_key. Ideally we would pass a "quiet" flag to the config machinery, but there are many layers between the pager code and the key parsing. Passing a flag through all of those would be an invasive change. Instead, let's provide a config function to report on whether a key is syntactically valid, and have the pager and alias code skip lookup for bogus keys. We can build this easily around the existing git_config_parse_key, with two minor modifications: 1. We now handle a NULL store_key, to validate but not write out the normalized key. 2. We accept a "quiet" flag to avoid writing to stderr. This doesn't need to be a full-blown public "flags" field, because we can make the existing implementation a static helper function, keeping the mess contained inside config.c. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
9e9de18
|
||
peff |
rev-list: make it obvious that we do not support notes
The rev-list command does not have the internal infrastructure to display notes. Running: git rev-list --notes HEAD will silently ignore the "--notes" option. Running: git rev-list --notes --grep=. HEAD will crash on an assert. Running: git rev-list --format=%N HEAD will place a literal "%N" in the output (it does not even expand to an empty string). Let's have rev-list tell the user that it cannot fill the user's request, rather than silently producing wrong data. Likewise, let's remove mention of the notes options from the rev-list documentation. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
2aea7a5
|
||
gitster |
builtin/am: introduce write_state_*() helper functions
There are many calls to write_file() that repeat the same pattern in the implementation of the builtin version of "am". They all share the same traits, i.e they - produce a text file with a single string in it; - have enough information to produce the entire contents of that file; - generate the pathname of the file by making a call to am_path(); and - they ask write_file() to die() upon failure. The slight differences among the call sites throw them into roughly three categories: - many write either "t" or "f" based on a boolean value to a file; - some write the integer value in decimal text; - some others write more general string, e.g. an object name in hex, an empty string (i.e. the presense of the file itself serves as a flag), etc. Introduce three helpers, write_state_bool(), write_state_count() and write_state_text(), to reduce direct calls to write_file(). This is a preparatory step for the next step to ensure that no "state" file this command leaves in $GIT_DIR is with an incomplete line at the end. Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
25b763b
|
||
gitster |
builtin/am: make sure state files are text
We forgot to terminate the payload given to write_file() with LF, resulting in files that end with an incomplete line. Teach the wrappers builtin/am uses to make sure it adds LF at the end as necessary. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
57c867e
|
||
gitster |
write_file(): drop "fatal" parameter
All callers except three passed 1 for the "fatal" parameter to ask this function to die upon error, but to a casual reader of the code, it was not all obvious what that 1 meant. Instead, split the function into two based on a common write_file_v() that takes the flag, introduce write_file_gently() as a new way to attempt creating a file without dying on error, and make three callers to call it. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
12d6ce1
|
Commits on Aug 25, 2015
oldsharp |
l10n: zh_CN: Update Git Glossary: "commit message"
Add "commit message" to glossary. Translate it as "提交信息". Signed-off-by: Ray Chen <oldsharp@gmail.com> |
667599e
|
||
szeder |
describe --contains: default to HEAD when no commit-ish is given
'git describe --contains' doesn't default to HEAD when no commit is given, and it doesn't produce any output, not even an error: ~/src/git ((v2.5.0))$ ./git describe --contains ~/src/git ((v2.5.0))$ ./git describe --contains HEAD v2.5.0^0 Unlike other 'git describe' options, the '--contains' code path is implemented by calling 'name-rev' with a bunch of options plus all the commit-ishes that were passed to 'git describe'. If no commit-ish was present, then 'name-rev' got invoked with none, which then leads to the behavior illustrated above. Porcelain commands usually default to HEAD when no commit-ish is given, and 'git describe' already does so in all other cases, so it should do so with '--contains' as well. Pass HEAD to 'name-rev' when no commit-ish is given on the command line to make '--contains' behave consistently with other 'git describe' options. While at it, use argv_array_pushv() instead of the loop to pass commit-ishes to 'git name-rev'. 'git describe's short help already indicates that the commit-ish is optional, but the synopsis in the man page doesn't, so update it accordingly as well. Signed-off-by: SZEDER Gábor <szeder@ira.uka.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
2bd0706
|
||
pclouds |
setup: update the right file in multiple checkouts
This code is introduced in 23af91d (prune: strategies for linked checkouts - 2014-11-30), and it's supposed to implement this rule from that commit's message: - linked checkouts are supposed to keep its location in $R/gitdir up to date. The use case is auto fixup after a manual checkout move. Note the name, "$R/gitdir", not "$R/gitfile". Correct the path to be updated accordingly. While at there, make sure I/O errors are not silently dropped. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
82fde87
|
||
sunshineco |
generate-cmdlist: re-implement as shell script
527ec39 (generate-cmdlist: parse common group commands, 2015-05-21) replaced generate-cmdlist.sh with a more functional Perl version, generate-cmdlist.perl. The Perl version gleans named tags from a new "common groups" section in command-list.txt and recognizes those tags in "command list" section entries in place of the old 'common' tag. This allows git-help to, not only recognize, but also group common commands. Although the tests require Perl, 527ec39 creates an unconditional dependence upon Perl in the build system itself, which can not be overridden with NO_PERL. Such a dependency may be undesirable; for instance, the 'git-lite' package in the FreeBSD ports tree is intended as a minimal Git installation (which may, for example, be useful on servers needing only local clone and update capability), which, historically, has not depended upon Perl[1]. Therefore, revive generate-cmdlist.sh and extend it to recognize "common groups" and its named tags. Retire generate-cmdlist.perl. [1]: http://thread.gmane.org/gmane.comp.version-control.git/275905/focus=276132 Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
82aec45
|
||
gitster |
write_file_v(): do not leave incomplete line at the end
All existing callers to this function use it to produce a text file or an empty file, and a new callsite that mimick them must end their payload with a LF. If they forget to do so, the resulting file will end with an incomplete line. Teach write_file_v() to complete the incomplete line, if exists, so that the callers do not have to. With this, the caller-side fix in builtin/am.c becomes unnecessary. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
e7ffa38
|
||
gitster |
write_file(): drop caller-supplied LF from calls to create a one-line…
…r file All of the callsites covered by this change call write_file() or write_file_gently() to create a one-liner file. Drop the caller supplied LF and let these callees to append it as necessary. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
1f76a10
|
||
gitster |
builtin/log.c: minor reformat
Two logical lines that were not overly long was split in the middle, which made them read worse. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
3acf8dd
|
||
gitster |
Merge branch 'jh/strbuf-read-use-read-in-full'
strbuf_read() used to have one extra iteration (and an unnecessary strbuf_grow() of 8kB), which was eliminated. * jh/strbuf-read-use-read-in-full: strbuf_read(): skip unnecessary strbuf_grow() at eof |
3b281d1
|
||
gitster |
Merge branch 'ee/clean-remove-dirs'
Test updates for Windows. * ee/clean-remove-dirs: t7300-clean: require POSIXPERM for chmod 0 test |
b590720
|
||
gitster |
Merge branch 'jk/long-error-messages'
The codepath to produce error messages had a hard-coded limit to the size of the message, primarily to avoid memory allocation while calling die(). * jk/long-error-messages: vreportf: avoid intermediate buffer vreportf: report to arbitrary filehandles |
1302c9f
|
||
gitster |
Merge branch 'nd/dwim-wildcards-as-pathspecs'
Test updates for Windows. * nd/dwim-wildcards-as-pathspecs: t2019: skip test requiring '*' in a file name non Windows |
5d5be81
|
||
gitster |
Merge branch 'dt/notes-multiple'
When linked worktree is used, simultaneous "notes merge" instances for the same ref in refs/notes/* are prevented from stomping on each other. * dt/notes-multiple: notes: handle multiple worktrees worktrees: add find_shared_symref |
32561f5
|
||
gitster |
Merge branch 'dt/refs-pseudo'
To prepare for allowing a different "ref" backend to be plugged in to the system, update_ref()/delete_ref() have been taught about ref-like things like MERGE_HEAD that are per-worktree (they will always be written to the filesystem inside $GIT_DIR). * dt/refs-pseudo: pseudoref: check return values from read_ref() sequencer: replace write_cherry_pick_head with update_ref bisect: use update_ref pseudorefs: create and use pseudoref update and delete functions refs: add ref_type function refs: introduce pseudoref and per-worktree ref concepts |
080cc64
|
||
gitster |
Merge branch 'pt/am-builtin-options'
After "git am --opt1" stops, running "git am --opt2" pays attention to "--opt2" only for the patch that caused the original invocation to stop. * pt/am-builtin-options: am: let --signoff override --no-signoff am: let command-line options override saved options test_terminal: redirect child process' stdin to a pty |
424f89f
|
||
gitster |
Merge branch 'mh/tempfile'
The "lockfile" API has been rebuilt on top of a new "tempfile" API. * mh/tempfile: credential-cache--daemon: use tempfile module credential-cache--daemon: delete socket from main() gc: use tempfile module to handle gc.pid file lock_repo_for_gc(): compute the path to "gc.pid" only once diff: use tempfile module setup_temporary_shallow(): use tempfile module write_shared_index(): use tempfile module register_tempfile(): new function to handle an existing temporary file tempfile: add several functions for creating temporary files prepare_tempfile_object(): new function, extracted from create_tempfile() tempfile: a new module for handling temporary files commit_lock_file(): use get_locked_file_path() lockfile: add accessor get_lock_file_path() lockfile: add accessors get_lock_file_fd() and get_lock_file_fp() create_bundle(): duplicate file descriptor to avoid closing it twice lockfile: move documentation to lockfile.h and lockfile.c |
db86e61
|
||
gitster |
Merge branch 'cb/open-noatime-clear-errno'
When trying to see that an object does not exist, a state errno leaked from our "first try to open a packfile with O_NOATIME and then if it fails retry without it" logic on a system that refuses O_NOATIME. This confused us and caused us to die, saying that the packfile is unreadable, when we should have just reported that the object does not exist in that packfile to the caller. * cb/open-noatime-clear-errno: git_open_noatime: return with errno=0 on success |
9b8d731
|
||
gitster |
Fifth batch for 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
8da8889
|
||
gitster |
pull: pass upload_pack only when it was given
The upload_pack shell variable is initialized to an empty string, so conditional expansion with ${upload_pack+"$upload_pack"} would not work very well. You need a colon there. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
13e0e28
|
||
gitster |
Merge branch 'mm/pull-upload-pack' into maint
"git pull" in recent releases of Git has a regression in the code that allows custom path to the --upload-pack=<program>. This has been corrected. Note that this is irrelevant for 'master' with "git pull" rewritten in C. * mm/pull-upload-pack: pull: pass upload_pack only when it was given pull.sh: quote $upload_pack when passing it to git-fetch |
425a4c7
|
||
gitster |
Merge branch 'sb/check-return-from-read-ref' into maint
* sb/check-return-from-read-ref: transport-helper: die on errors reading refs. |
7a23807
|
||
gitster |
Merge branch 'jk/test-with-x' into maint
Running tests with the "-x" option to make them verbose had some unpleasant interactions with other features of the test suite. * jk/test-with-x: test-lib: disable trace when test is not verbose test-lib: turn off "-x" tracing during chain-lint check |
84deb3e
|
||
gitster |
Merge branch 'jk/guess-repo-name-regression-fix' into maint
"git clone $URL" in recent releases of Git contains a regression in the code that invents a new repository name incorrectly based on the $URL. This has been corrected. * jk/guess-repo-name-regression-fix: clone: use computed length in guess_dir_name clone: add tests for output directory |
52f6893
|
||
gitster |
Sync with maint
* maint: pull: pass upload_pack only when it was given |
33f2c4f
|
Commits on Aug 26, 2015
javabrett |
git-svn doc: mention "svn-remote.<name>.include-paths"
Mention the configuration variable in a way similar to how "svn-remote.<name>.ignore-paths" is mentioned. Signed-off-by: Brett Randall <javabrett@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
486e1e1
|
||
Christian Couder |
trailer: retitle a test and correct an in-comment message
Signed-off-by: Christian Couder <christian.couder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
6262fe9
|
||
jiangxin |
i18n: am: fix typo in description of -b option
Signed-off-by: Jiang Xin <worldhello.net@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
1fb5a0e
|
||
gitster |
Merge branch 'ss/fix-config-fd-leak'
* ss/fix-config-fd-leak: config: close config file handle in case of error |
51e83a4
|
||
gitster |
Merge branch 'ep/http-configure-ssl-version'
A new configuration variable http.sslVersion can be used to specify what specific version of SSL/TLS to use to make a connection. * ep/http-configure-ssl-version: http: add support for specifying the SSL version |
ed070a4
|
||
gitster |
Merge branch 'jv/send-email-selective-smtp-auth'
"git send-email" learned a new option --smtp-auth to limit the SMTP AUTH mechanisms to be used to a subset of what the system library supports. * jv/send-email-selective-smtp-auth: send-email: provide whitelist of SMTP AUTH mechanisms |
629ac65
|
||
gitster |
Merge branch 'po/po-readme'
* po/po-readme: po/README: Update directions for l10n contributors |
788f211
|
||
gitster |
Merge branch 'pt/am-builtin-abort-fix'
"git am" that was recently reimplemented in C had a performance regression in "git am --abort" that goes back to the version before an attempted (and failed) patch application. * pt/am-builtin-abort-fix: am --skip/--abort: merge HEAD/ORIG_HEAD tree into index |
b7d2a15
|
||
gitster |
Merge branch 'pt/am-builtin'
Rewrite "am" in "C". * pt/am-builtin: i18n: am: fix typo in description of -b option |
74702c3
|
||
gitster |
Merge branch 'dt/untracked-sparse'
Test update. * dt/untracked-sparse: t7063: use --force-untracked-cache to speed up a bit |
a5315dd
|
||
gitster |
Merge branch 'jc/calloc-pathspec'
* jc/calloc-pathspec: ps_matched: xcalloc() takes nmemb and then element size |
88bd19b
|
||
gitster |
Merge branch 'sg/t3020-typofix'
* sg/t3020-typofix: t3020: fix typo in test description |
7205e22
|
||
gitster |
Merge branch 'as/docfix-reflog-expire-unreachable'
* as/docfix-reflog-expire-unreachable: Documentation/config: fix inconsistent label on gc.*.reflogExpireUnreachable |
cfcd38f
|
||
gitster |
Merge branch 'sg/wt-status-header-inclusion'
* sg/wt-status-header-inclusion: wt-status: move #include "pathspec.h" to the header |
6525496
|
||
gitster |
Merge branch 'sg/help-group'
We rewrote one of the build scripts in Perl but this reimplements in Bourne shell. * sg/help-group: generate-cmdlist: re-implement as shell script |
678c5a4
|
||
gitster |
Sixth batch for 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
3a9835b
|
Commits on Aug 28, 2015
René Scharfe |
t5004: test ZIP archives with many entries
A ZIP file directory has a 16-bit field for the number of entries it contains. There are 64-bit extensions to deal with that. Demonstrate that git archive --format=zip currently doesn't use them and instead overflows the field. InfoZIP's unzip doesn't care about this field and extracts all files anyway. Software that uses the directory for presenting a filesystem like view quickly -- notably Windows -- depends on it, but doesn't lend itself to an automatic test case easily. Use InfoZIP's zipinfo, which probably isn't available everywhere but at least can provides *some* way to check this field. To speed things up a bit create and commit only a subset of the files and build a fake tree out of duplicates and pass that to git archive. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
19ee294
|
||
René Scharfe |
archive-zip: use a local variable to store the creator version
Use a simpler conditional right next to the code which makes a higher creator version necessary -- namely symlink handling and support for executable files -- instead of a long line with a ternary operator. The resulting code has more lines but is simpler and allows reuse of the value easily. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
0f747f9
|
||
René Scharfe |
archive-zip: support more than 65535 entries
Support more than 65535 entries cleanly by writing a "zip64 end of central directory record" (with a 64-bit field for the number of entries) before the usual "end of central directory record" (which contains only a 16-bit field). InfoZIP's zip does the same. Archives with 65535 or less entries are not affected. Programs that extract all files like InfoZIP's zip and 7-Zip ignored the field and could extract all files already. Software that relies on the ZIP file directory to show a list of contained files quickly to simulate to normal directory like Windows' built-in ZIP functionality only saw a subset of the included files. Windows supports ZIP64 since Vista according to https://en.wikipedia.org/wiki/Zip_%28file_format%29#ZIP64. Suggested-by: Johannes Schauer <josch@debian.org> Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
88329ca
|
||
alexhenrie |
reflog: add missing single quote to error message
The error message can be seen by running `git config gc.reflogexpire foo` and then `git reflog expire`. Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
99885bc
|
||
larsxschneider |
git-p4: honor core.ignorecase when using P4 client specs
Perforce depot may record paths in mixed cases, e.g. "p4 files" may show that there are these two paths: //depot/Path/to/file1 //depot/pATH/to/file2 and with "p4" or "p4v", these end up in the same directory, e.g. //depot/Path/to/file1 //depot/Path/to/file2 which is the desired outcome on case insensitive systems. If git-p4 is used with client spec "//depot/Path/...", however, then all files not matching the case in the client spec are ignored (in the example above "//depot/pATH/to/file2"). Fix this by using the path case that appears first in lexicographical order when core.ignorecase is set to true. This behavior is consistent with "p4" and "p4v". Signed-off-by: Lars Schneider <larsxschneider@gmail.com> Acked-by: Luke Diamand <luke@diamand.org> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
a0a50d8
|
||
jfmc |
Mingw: verify both ends of the pipe () call
The code to open and test the second end of the pipe clearly imitates the code for the first end. A little too closely, though... Let's fix the obvious copy-edit bug. Signed-off-by: Jose F. Morales <jfmcjf@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Acked-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
c3cb7b6
|
||
gitster |
Git 2.5.1
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
c415fb7
|
||
ralfth |
lockfile: remove function "hold_lock_file_for_append"
With 77b9b1d (add_to_alternates_file: don't add duplicate entries, 2015-08-10) the last caller of function "hold_lock_file_for_append" has been removed, so we can remove the function as well. Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com> Acked-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
aae42e4
|
||
alexhenrie |
git-submodule: remove extraneous space from error message
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Acked-by: Chris Packham <judge.packham@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
b80fa84
|
||
alexhenrie |
pack-objects: place angle brackets around placeholders in usage strings
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
b8c1d27
|
||
alexhenrie |
read-tree: replace bracket set with parentheses to clarify usage
-u and -i can only be given if -m, --reset, or --prefix is given. Without parentheses, it looks like -u and -i can be used no matter what, and the second pair of brackets is confusing. Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
9476c2c
|
||
gitster |
Merge branch 'dt/untracked-subdir'
The experimental untracked-cache feature were buggy when paths with a few levels of subdirectories are involved. * dt/untracked-subdir: untracked cache: fix entry invalidation untracked-cache: fix subdirectory handling |
038226e
|
||
gitster |
Merge branch 'cc/trailers-corner-case-fix'
"interpret-trailers" helper mistook a single-liner log message that has a colon as the end of existing trailer. * cc/trailers-corner-case-fix: trailer: retitle a test and correct an in-comment message trailer: ignore first line of message |
483c9b8
|
||
gitster |
Seventh batch for 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
e6837c8
|
||
gitster |
Sync with 2.5.1
|
aecce6d
|
Commits on Aug 31, 2015
dturner-tw |
commit: don't rewrite shared index unnecessarily
Remove a cache invalidation which would cause the shared index to be rewritten on as-is commits. When the cache-tree has changed, we need to update it. But we don't necessarily need to update the shared index. So setting active_cache_changed to SOMETHING_CHANGED is unnecessary. Instead, we let update_main_cache_tree just update the CACHE_TREE_CHANGED bit. In order to test this, make test-dump-split-index not segfault on missing replace_bitmap/delete_bitmap. This new codepath is not called now that the test passes, but is necessary to avoid a segfault when the new test is run with the old builtin/commit.c code. Signed-off-by: David Turner <dturner@twopensource.com> Acked-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
475a344
|
||
alexhenrie |
show-ref: place angle brackets around variables in usage string
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
cc75add
|
||
peff |
log: diagnose empty HEAD more clearly
If you init or clone an empty repository, the initial message from running "git log" is not very friendly: $ git init Initialized empty Git repository in /home/peff/foo/.git/ $ git log fatal: bad default revision 'HEAD' Let's detect this situation and write a more friendly message: $ git log fatal: your current branch 'master' does not have any commits yet We also detect the case that 'HEAD' points to a broken ref; this should be even less common, but is easy to see. Note that we do not diagnose all possible cases. We rely on resolve_ref, which means we do not get information about complex cases. E.g., "--default master" would use dwim_ref to find "refs/heads/master", but we notice only that "master" does not exist. Similarly, a complex sha1 expression like "--default HEAD^2" will not resolve as a ref. But that's OK. We fall back to a generic error message in those cases, and they are unlikely to be used anyway. Catching an empty or broken "HEAD" improves the common case, and the other cases are not regressed. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
ce11360
|
||
elfstrom |
t7300: fix broken && chains
While we are here, remove some boilerplate by using test_commit. Signed-off-by: Erik Elfström <erik.elfstrom@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
1733ed3
|
||
Christian Couder |
trailer: support multiline title
We currently ignore the first line passed to `git interpret-trailers`, when looking for the beginning of the trailers. Unfortunately this does not work well when a commit is created with a line break in the title, using for example the following command: git commit -m 'place of code: change we made' That's why instead of ignoring only the first line, it is better to ignore the first paragraph. Signed-off-by: Christian Couder <christian.couder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
5c99995
|
||
stefanbeller |
read-cache: fix indentation in read_index_from
Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
6bea53c
|
||
gitster |
Merge branch 'sg/config-name-only'
"git config --list" output was hard to parse when values consist of multiple lines. "--name-only" option is added to help this. * sg/config-name-only: get_urlmatch: avoid useless strbuf write format_config: simplify buffer handling format_config: don't init strbuf config: restructure format_config() for better control flow completion: list variable names reliably with 'git config --name-only' config: add '--name-only' option to list only variable names |
fc9dfda
|
||
gitster |
Merge branch 'hv/submodule-config'
The gitmodules API accessed from the C code learned to cache stuff lazily. * hv/submodule-config: submodule: allow erroneous values for the fetchRecurseSubmodules option submodule: use new config API for worktree configurations submodule: extract functions for config set and lookup submodule: implement a config API for lookup of .gitmodules values |
5a4f07b
|
||
gitster |
Merge branch 'jk/rev-list-has-no-notes'
"git rev-list" does not take "--notes" option, but did not complain when one is given. * jk/rev-list-has-no-notes: rev-list: make it obvious that we do not support notes |
0bb71fb
|
||
gitster |
Merge branch 'jk/fix-alias-pager-config-key-warnings'
Because the configuration system does not allow "alias.0foo" and "pager.0foo" as the configuration key, the user cannot use '0foo' as a custom command name anyway, but "git 0foo" tried to look these keys up and emitted useless warnings before saying '0foo is not a git command'. These warning messages have been squelched. * jk/fix-alias-pager-config-key-warnings: config: silence warnings for command names with invalid keys |
7b7c10b
|
||
gitster |
Merge branch 'jc/log-p-cc'
"git log --cc" did not show any patch, even though most of the time the user meant "git log --cc -p -m" to see patch output for commits with a single parent, and combined diff for merge commits. The command is taught to DWIM "--cc" (without "--raw" and other forms of output specification) to "--cc -p -m". * jc/log-p-cc: builtin/log.c: minor reformat log: show merge commit when --cc is given log: when --cc is given, default to -p unless told otherwise log: rename "tweak" helpers |
2ba6183
|
||
gitster |
Merge branch 'jc/am-state-fix'
Recent reimplementation of "git am" changed the format of state files kept in $GIT_DIR/rebase-apply/ without meaning to do so, primarily because write_file() API was cumbersome to use and it was easy to mistakenly make text files with incomplete lines. Update write_file() interface to make it harder to misuse. * jc/am-state-fix: write_file(): drop caller-supplied LF from calls to create a one-liner file write_file_v(): do not leave incomplete line at the end write_file(): drop "fatal" parameter builtin/am: make sure state files are text builtin/am: introduce write_state_*() helper functions |
d75bb73
|
||
gitster |
Merge branch 'jk/notes-merge-config'
"git notes merge" can be told with "--strategy=<how>" option how to automatically handle conflicts; this can now be configured by setting notes.mergeStrategy configuration variable. * jk/notes-merge-config: notes: teach git-notes about notes.<name>.mergeStrategy option notes: add notes.mergeStrategy option to select default strategy notes: add tests for --commit/--abort/--strategy exclusivity notes: extract parse_notes_merge_strategy to notes-utils notes: extract enum notes_merge_strategy to notes-utils.h notes: document cat_sort_uniq rewriteMode |
5b6211a
|
||
gitster |
Merge branch 'db/push-sign-if-asked'
The client side codepaths in "git push" have been cleaned up and the user can request to perform an optional "signed push", i.e. sign only when the other end accepts signed push. * db/push-sign-if-asked: push: add a config option push.gpgSign for default signed pushes push: support signing pushes iff the server supports it builtin/send-pack.c: use parse_options API config.c: rename git_config_maybe_bool_text and export it as git_parse_maybe_bool transport: remove git_transport_options.push_cert gitremote-helpers.txt: document pushcert option Documentation/git-send-pack.txt: document --signed Documentation/git-send-pack.txt: wrap long synopsis line Documentation/git-push.txt: document when --signed may fail |
b21089d
|
||
gitster |
Merge branch 'sg/describe-contains'
"git describe" without argument defaulted to describe the HEAD commit, but "git describe --contains" didn't. Arguably, in a repository used for active development, such defaulting would not be very useful as the tip of branch is typically not tagged, but it is better to be consistent. * sg/describe-contains: describe --contains: default to HEAD when no commit-ish is given |
e95c3fb
|
||
gitster |
Eighth batch for 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
1616360
|
Commits on Sep 01, 2015
peff |
rerere: release lockfile in non-writing functions
There's a bug in builtin/am.c in which we take a lock on MERGE_RR recursively. But rather than fix am.c, this patch fixes the confusing interface from rerere.c that caused the bug. Read on for the gory details. The setup_rerere() function both reads the existing MERGE_RR file, and takes MERGE_RR.lock. In the rerere() and rerere_forget() functions, we end up in write_rr(), which will then commit the lock file. But for functions like rerere_clear() that do not write to MERGE_RR, we expect the caller to have handled setup_rerere(). That caller would then need to release the lockfile, but it can't; the lock struct is local to rerere.c. For builtin/rerere.c, this is OK. We run a single rerere operation and then exit immediately, which has the side effect of rolling back the lockfile. But in builtin/am.c, this is actively wrong. If we run "git am -3 --skip", we call setup-rerere twice without releasing the lock: 1. The "--skip" causes us to call am_rerere_clear(), which calls setup_rerere(), but never drops the lock. 2. We then proceed to the next patch. 3. The "--3way" may cause us to call rerere() to handle conflicts in that patch, but we are already holding the lock. The lockfile code dies with: BUG: prepare_tempfile_object called for active object We could fix this by having rerere_clear() call rollback_lock_file(). But it feels a bit odd for it to roll back a lockfile that it did not itself take. So let's simplify the interface further, and handle setup_rerere in the function itself, taking away the question from the caller over whether they need to do so. We can give rerere_gc() the same treatment, as well (even though it doesn't have any callers besides builtin/rerere.c at this point). Note that these functions don't take flags from their callers to pass along to setup_rerere; that's OK, because the flags would not be meaningful for what they are doing. Both of those functions need to hold the lock because even though they do not write to MERGE_RR, they are still writing and should be protected from a simultaneous "rerere" run. But rerere_remaining(), "rerere diff", and "rerere status" are all read-only operations. They want to setup_rerere(), but do not care about taking the lock in the first place. Since our update of MERGE_RR is the usual atomic rename done by commit_lock_file, they can just do a lockless read. For that, we teach setup_rerere a READONLY flag to avoid the lock. As a bonus, this pushes builtin/rerere.c's setup_rerere call closer to the functions that use it. Which means that "git rerere totally-bogus-command" will no longer silently exit(0) in a repository without rerere enabled. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
9dd330e
|
||
gitster |
Merge branch 'nd/fixup-linked-gitdir'
The code in "multiple-worktree" support that attempted to recover from an inconsistent state updated an incorrect file. * nd/fixup-linked-gitdir: setup: update the right file in multiple checkouts |
91d5469
|
||
gitster |
Merge branch 'br/svn-doc-include-paths-config'
* br/svn-doc-include-paths-config: git-svn doc: mention "svn-remote.<name>.include-paths" |
49c15c0
|
||
gitster |
Merge branch 'ah/pack-objects-usage-strings'
Usage string fix. * ah/pack-objects-usage-strings: pack-objects: place angle brackets around placeholders in usage strings |
8746e30
|
||
gitster |
Merge branch 'ah/read-tree-usage-string'
Usage string fix. * ah/read-tree-usage-string: read-tree: replace bracket set with parentheses to clarify usage |
0b20a46
|
||
gitster |
Merge branch 'ah/reflog-typofix-in-error'
Error string fix. * ah/reflog-typofix-in-error: reflog: add missing single quote to error message |
bc1c600
|
||
gitster |
Merge branch 'ah/submodule-typofix-in-error'
Error string fix. * ah/submodule-typofix-in-error: git-submodule: remove extraneous space from error message |
2953140
|
||
gitster |
Merge branch 'ls/p4-fold-case-client-specs'
On case insensitive systems, "git p4" did not work well with client specs. * ls/p4-fold-case-client-specs: git-p4: honor core.ignorecase when using P4 client specs |
bb84dce
|
||
gitster |
Merge branch 'rs/archive-zip-many'
"git archive" did not use zip64 extension when creating an archive with more than 64k entries, which nobody should need, right ;-)? * rs/archive-zip-many: archive-zip: support more than 65535 entries archive-zip: use a local variable to store the creator version t5004: test ZIP archives with many entries |
565f575
|
||
gitster |
Merge branch 'rt/remove-hold-lockfile-for-append'
* rt/remove-hold-lockfile-for-append: lockfile: remove function "hold_lock_file_for_append" |
0fb8e24
|
||
gitster |
Merge branch 'dt/commit-preserve-base-index-upon-opportunistic-cache-…
…tree-update' When re-priming the cache-tree opportunistically while committing the in-core index as-is, we mistakenly invalidated the in-core index too aggressively, causing the experimental split-index code to unnecessarily rewrite the on-disk index file(s). * dt/commit-preserve-base-index-upon-opportunistic-cache-tree-update: commit: don't rewrite shared index unnecessarily |
81d0e33
|
||
gitster |
Ninth batch for 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
7aa67f6
|
Commits on Sep 02, 2015
matthieuprat |
t7060: actually test "git diff-index --cached -M"
A test was designed for "git diff-index --cached -M" but the command is run without the "-M" option (which makes the test essentially identical to its preceding counterpart). Signed-off-by: Matthieu Prat <matthieuprat@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
b894d3e
|
||
gitster |
Merge branch 'jk/log-missing-default-HEAD'
"git init empty && git -C empty log" said "bad default revision 'HEAD'", which was found to be a bit confusing to new users. * jk/log-missing-default-HEAD: log: diagnose empty HEAD more clearly |
699a0f3
|
||
gitster |
Merge branch 'ee/clean-test-fixes'
* ee/clean-test-fixes: t7300: fix broken && chains |
83d9092
|
||
gitster |
Merge branch 'sb/read-cache-one-indent-style-fix'
* sb/read-cache-one-indent-style-fix: read-cache: fix indentation in read_index_from |
8f8386e
|
||
gitster |
Merge branch 'cc/trailers-corner-case-fix'
The "interpret-trailers" helper mistook a multi-paragraph title of a commit log message with a colon in it as the end of the trailer block. * cc/trailers-corner-case-fix: trailer: support multiline title |
cdd00df
|
||
gitster |
Git 2.6-rc0
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
16ffa64
|
Commits on Sep 03, 2015
gitster |
Merge branch 'jk/am-rerere-lock-fix'
Recent "git am" introduced a double-locking failure when used with the "--3way" option that invokes rerere machinery. * jk/am-rerere-lock-fix: rerere: release lockfile in non-writing functions |
7662973
|
||
peff |
pack-protocol: clarify LF-handling in PKT-LINE()
The spec is very inconsistent about which PKT-LINE() parts of the grammar include a LF. On top of that, the code is not consistent, either (e.g., send-pack does not put newlines into the ref-update commands it sends). Let's make explicit the long-standing expectation that we generally expect pkt-lines to end in a newline, but that receivers should be lenient. This makes the spec consistent, and matches what git already does (though it does not always fulfill the SHOULD). We do make an exception for the push-cert, where the receiving code is currently a bit pickier. This is a reasonable way to be, as the data needs to be byte-for-byte compatible with what was signed. We _could_ make up some rules about signing a canonicalized version including newlines, but that would require a code change, and is out of scope for this patch. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
1c9b659
|
Commits on Sep 04, 2015
gitster |
Merge branch 'mh/get-remote-group-fix' into maint
An off-by-one error made "git remote" to mishandle a remote with a single letter nickname. * mh/get-remote-group-fix: get_remote_group(): use skip_prefix() get_remote_group(): eliminate superfluous call to strcspn() get_remote_group(): rename local variable "space" to "wordlen" get_remote_group(): handle remotes with single-character names |
03ea027
|
||
gitster |
Merge branch 'cb/open-noatime-clear-errno' into maint
When trying to see that an object does not exist, a state errno leaked from our "first try to open a packfile with O_NOATIME and then if it fails retry without it" logic on a system that refuses O_NOATIME. This confused us and caused us to die, saying that the packfile is unreadable, when we should have just reported that the object does not exist in that packfile to the caller. * cb/open-noatime-clear-errno: git_open_noatime: return with errno=0 on success |
cbcd3dc
|
||
gitster |
Merge branch 'jk/long-error-messages' into maint
The codepath to produce error messages had a hard-coded limit to the size of the message, primarily to avoid memory allocation while calling die(). * jk/long-error-messages: vreportf: avoid intermediate buffer vreportf: report to arbitrary filehandles |
6c0850f
|
||
gitster |
Merge branch 'jh/strbuf-read-use-read-in-full' into maint
strbuf_read() used to have one extra iteration (and an unnecessary strbuf_grow() of 8kB), which was eliminated. * jh/strbuf-read-use-read-in-full: strbuf_read(): skip unnecessary strbuf_grow() at eof |
8b27071
|
||
gitster |
Merge branch 'ps/t1509-chroot-test-fixup' into maint
t1509 test that requires a dedicated VM environment had some bitrot, which has been corrected. * ps/t1509-chroot-test-fixup: tests: fix cleanup after tests in t1509-root-worktree tests: fix broken && chains in t1509-root-worktree |
d11448f
|
||
gitster |
Merge branch 'sg/help-group' into maint
We rewrote one of the build scripts in Perl but this reimplements in Bourne shell. * sg/help-group: generate-cmdlist: re-implement as shell script |
969560b
|
||
gitster |
Merge branch 'nd/dwim-wildcards-as-pathspecs' into maint
Test updates for Windows. * nd/dwim-wildcards-as-pathspecs: t2019: skip test requiring '*' in a file name non Windows |
0b2cef2
|
||
gitster |
Merge branch 'jk/fix-alias-pager-config-key-warnings' into maint
Because the configuration system does not allow "alias.0foo" and "pager.0foo" as the configuration key, the user cannot use '0foo' as a custom command name anyway, but "git 0foo" tried to look these keys up and emitted useless warnings before saying '0foo is not a git command'. These warning messages have been squelched. * jk/fix-alias-pager-config-key-warnings: config: silence warnings for command names with invalid keys |
fa6d374
|
||
gitster |
Merge branch 'jk/rev-list-has-no-notes' into maint
"git rev-list" does not take "--notes" option, but did not complain when one is given. * jk/rev-list-has-no-notes: rev-list: make it obvious that we do not support notes |
e654e3b
|
||
gitster |
Merge branch 'nd/fixup-linked-gitdir' into maint
The code in "multiple-worktree" support that attempted to recover from an inconsistent state updated an incorrect file. * nd/fixup-linked-gitdir: setup: update the right file in multiple checkouts |
d6c196a
|
||
gitster |
Merge branch 'as/docfix-reflog-expire-unreachable' into maint
Docfix. * as/docfix-reflog-expire-unreachable: Documentation/config: fix inconsistent label on gc.*.reflogExpireUnreachable |
c1fa16b
|
||
gitster |
Merge branch 'sg/t3020-typofix' into maint
* sg/t3020-typofix: t3020: fix typo in test description |
57a2bb1
|
||
gitster |
Merge branch 'po/po-readme' into maint
Doc updates for i18n. * po/po-readme: po/README: Update directions for l10n contributors |
659227b
|
||
gitster |
Merge branch 'sg/wt-status-header-inclusion' into maint
* sg/wt-status-header-inclusion: wt-status: move #include "pathspec.h" to the header |
dc4e7b0
|
||
gitster |
Merge branch 'ss/fix-config-fd-leak' into maint
* ss/fix-config-fd-leak: config: close config file handle in case of error |
8136099
|
||
gitster |
Merge branch 'jc/calloc-pathspec' into maint
Minor code cleanup. * jc/calloc-pathspec: ps_matched: xcalloc() takes nmemb and then element size |
ae6ac84
|
||
gitster |
Merge branch 'rs/archive-zip-many' into maint
"git archive" did not use zip64 extension when creating an archive with more than 64k entries, which nobody should need, right ;-)? * rs/archive-zip-many: archive-zip: support more than 65535 entries archive-zip: use a local variable to store the creator version t5004: test ZIP archives with many entries |
1c82039
|
||
gitster |
Merge branch 'dt/commit-preserve-base-index-upon-opportunistic-cache-…
…tree-update' into maint When re-priming the cache-tree opportunistically while committing the in-core index as-is, we mistakenly invalidated the in-core index too aggressively, causing the experimental split-index code to unnecessarily rewrite the on-disk index file(s). * dt/commit-preserve-base-index-upon-opportunistic-cache-tree-update: commit: don't rewrite shared index unnecessarily |
311e5ce
|
||
gitster |
Merge branch 'cc/trailers-corner-case-fix' into maint
The "interpret-trailers" helper mistook a multi-paragraph title of a commit log message with a colon in it as the end of the trailer block. * cc/trailers-corner-case-fix: trailer: support multiline title trailer: retitle a test and correct an in-comment message trailer: ignore first line of message |
9d93988
|
||
gitster |
Merge branch 'jk/log-missing-default-HEAD' into maint
"git init empty && git -C empty log" said "bad default revision 'HEAD'", which was found to be a bit confusing to new users. * jk/log-missing-default-HEAD: log: diagnose empty HEAD more clearly |
5af77d1
|
||
gitster |
Merge branch 'ee/clean-test-fixes' into maint
* ee/clean-test-fixes: t7300: fix broken && chains |
fb8880d
|
||
peff |
verify_absent: allow filenames longer than PATH_MAX
When unpack-trees wants to know whether a path will overwrite anything in the working tree, we use lstat() to see if there is anything there. But if we are going to write "foo/bar", we can't just lstat("foo/bar"); we need to look for leading prefixes (e.g., "foo"). So we use the lstat cache to find the length of the leading prefix, and copy the filename up to that length into a temporary buffer (since the original name is const, we cannot just stick a NUL in it). The copy we make goes into a PATH_MAX-sized buffer, which will overflow if the prefix is longer than PATH_MAX. How this happens is a little tricky, since in theory PATH_MAX is the biggest path we will have read from the filesystem. But this can happen if: - the compiled-in PATH_MAX does not accurately reflect what the filesystem is capable of - the leading prefix is not _quite_ what is on disk; it contains the next element from the name we are checking. So if we want to write "aaa/bbb/ccc/ddd" and "aaa/bbb" exists, the prefix of interest is "aaa/bbb/ccc". If "aaa/bbb" approaches PATH_MAX, then "ccc" can overflow it. So this can be triggered, but it's hard to do. In particular, you cannot just "git clone" a bogus repo. The verify_absent checks happen before unpack-trees writes anything to the filesystem, so there are never any leading prefixes during the initial checkout, and the bug doesn't trigger. And by definition, these files are larger than PATH_MAX, so writing them will fail, and clone will complain (though it may write a partial path, which will cause a subsequent "git checkout" to hit the bug). We can fix it by creating the temporary path on the heap. The extra malloc overhead is not important, as we are already making at least one stat() call (and probably more for the prefix discovery). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
f514ef9
|
||
peff |
notes: use a strbuf in add_non_note
When we are loading a notes tree into our internal hash table, we also collect any files that are clearly non-notes. We format the name of the file into a PATH_MAX buffer, but unlike true notes (which cannot be larger than a fanned-out sha1 hash), these tree entries can be arbitrarily long, overflowing our buffer. We can fix this by switching to a strbuf. It doesn't even cost us an extra allocation, as we can simply hand ownership of the buffer over to the non-note struct. This is of moderate security interest, as you might fetch notes trees from an untrusted remote. However, we do not do so by default, so you would have to manually fetch into the notes namespace. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
c29edfe
|
||
peff |
read_info_alternates: handle paths larger than PATH_MAX
This function assumes that the relative_base path passed into it is no larger than PATH_MAX, and writes into a fixed-size buffer. However, this path may not have actually come from the filesystem; for example, add_submodule_odb generates a path using a strbuf and passes it in. This is hard to trigger in practice, though, because the long submodule directory would have to exist on disk before we would try to open its info/alternates file. We can easily avoid the bug, though, by simply creating the filename on the heap. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
5015f01
|
||
peff |
show-branch: use a strbuf for reflog descriptions
When we show "branch@{0}", we format into a fixed-size buffer using sprintf. This can overflow if you have long branch names. We can fix it by using a temporary strbuf. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
78f23bd
|
||
gitster |
Merge branch 'jk/long-paths' into maint-2.2
|
f54cb05
|
||
gitster |
Git 2.2.3
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
441c4a4
|
||
gitster |
Sync with 2.2.3
|
8267cd1
|
||
gitster |
Git 2.3.9
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
ecad27c
|
||
gitster |
Sync with 2.3.9
|
ef0e938
|
||
gitster |
Git 2.4.9
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
74b6763
|
||
gitster |
Sync with 2.4.9
|
3d3caf0
|
||
gitster |
Git 2.5.2
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
27ea6f8
|
||
gitster |
Sync with maint
* maint: |
ec371ff
|
Commits on Sep 05, 2015
jiangxin |
l10n: git.pot: v2.6.0 round 1 (123 new, 41 removed)
Generate po/git.pot from v2.6.0-rc0-24-gec371ff for git v2.6.0 l10n round 1. Signed-off-by: Jiang Xin <worldhello.net@gmail.com> |
df0617b
|
||
jiangxin |
Merge branch 'master' of github.com:jiangxin/git into master
* 'master' of github.com:jiangxin/git: l10n: zh_CN: Update Git Glossary: "commit message" l10n: zh_CN: Update Git Glossary: pickaxe l10n: zh_CN: Update Git Glossary: fork l10n: zh_CN: Update Git Glossary: tag l10n: zh_CN: Update Git Glossary: "dumb", "smart" l10n: zh_CN: Update Git Glossary: SHA-1 l10n: zh_CN: Add Surrounding Spaces l10n: zh_CN: Add translations for Git glossary l10n: TEAMS: stash inactive zh_CN team members l10n: zh_CN: Update Translation of "tag" l10n: zh_CN: Unify Translation of "packfile" l10n: zh_CN: Update Translation: "tag object" Signed-off-by: Jiang Xin <worldhello.net@gmail.com> |
9049ba7
|
Commits on Sep 07, 2015
vnwildman |
l10n: Updated Vietnamese translation (2441t)
Signed-off-by: Tran Ngoc Quan <vnwildman@gmail.com> |
f299388
|
||
gitster |
am: match --signoff to the original scripted version
Linus noticed that the recently reimplemented "git am -s" defines the trailer block too rigidly, resulting in an unnecessary blank line between the existing sign-offs and his new sign-off. An e-mail submission sent to Linus in real life ends with mixture of sign-offs and commentaries, e.g. title here message here Signed-off-by: Original Author <original@auth.or> [rv: tweaked frotz and nitfol] Signed-off-by: Re Viewer <rv@ew.er> Signed-off-by: Other Reviewer <other@rev.ewer> --- patch here Because the reimplementation reused append_signoff() helper that is used by other codepaths, which is unaware that people intermix such comments with their sign-offs in the trailer block, such a message was judged to end with a non-trailer, resulting in an extra blank line before adding a new sign-off. The original scripted version of "git am" used a lot looser definition, i.e. "if and only if there is no line that begins with Signed-off-by:, add a blank line before adding a new sign-off". For the upcoming release, stop using the append_signoff() in "git am" and reimplement the looser definition used by the scripted version to use only in "git am" to fix this regression in "am" while avoiding new regressions to other users of append_signoff(). In the longer term, we should look into loosening append_signoff() so that other codepaths that add a new sign-off behave the same way as "git am -s", but that is a task for post-release. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
aab8454
|
Commits on Sep 08, 2015
jiangxin |
l10n: zh_CN: for git v2.6.0 l10n round 1
Update 123 translations (2441t0f0u) for git v2.6.0-rc0. Signed-off-by: Jiang Xin <worldhello.net@gmail.com> Reviewed-by: Ray Chen <oldsharp@gmail.com> |
1b7f4a3
|
||
gitster |
Merge branch 'jc/builtin-am-signoff-regression-fix'
Recent "git am" had regression when adding a Signed-off-by line with its "-s" option by an unintended tightening of how an existing trailer block is detected. * jc/builtin-am-signoff-regression-fix: am: match --signoff to the original scripted version |
d6a2b05
|
||
gitster |
Git 2.6-rc1
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
689efb7
|
Commits on Sep 09, 2015
Oblomov |
apply: comment grammar fix
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
5fcadc3
|
||
gitster |
Release Notes: typofix
Thanks to Andreas Schwab for careful reading. Signed-off-by: Junio C Hamano <gitster@pobox.com> |
7a2c4af
|
||
nafmo |
l10n: sv.po: Update Swedish translation (2441t0f0u)
Signed-off-by: Peter Krefting <peter@softwolves.pp.se> |
d8455d1
|
||
dscho |
am --skip/--abort: merge HEAD/ORIG_HEAD tree into index
f8da680 (am --skip: support skipping while on unborn branch, 2015-06-06) introduced a performance regression to "git am --skip", where it used "read-tree" to reconstruct the index from scratch without reusing the cached stat information. This is a backport of the corresponding patch to the builtin am in 2.6: 3ecc704 (am --skip/--abort: merge HEAD/ORIG_HEAD tree into index, 2015-08-19). Reportedly, it can make a huge difference on Windows, in one case a `git rebase --skip` took 1m40s without, and 5s with, this patch. cf. git-for-windows#365 Reported-and-suggested-by: Kim Gybels <kgybels@infogroep.be> Acked-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
b9d6689
|
||
gitster |
Sync with 2.5.2
|
f0bc854
|
Commits on Sep 10, 2015
jiangxin |
Merge branch 'master' of github.com:jiangxin/git
* 'master' of github.com:jiangxin/git: l10n: zh_CN: for git v2.6.0 l10n round 1 l10n: zh_CN: Update Git Glossary: "commit message" l10n: zh_CN: Update Git Glossary: pickaxe l10n: zh_CN: Update Git Glossary: fork l10n: zh_CN: Update Git Glossary: tag l10n: zh_CN: Update Git Glossary: "dumb", "smart" l10n: zh_CN: Update Git Glossary: SHA-1 l10n: zh_CN: Add Surrounding Spaces l10n: zh_CN: Add translations for Git glossary l10n: TEAMS: stash inactive zh_CN team members l10n: zh_CN: Update Translation of "tag" l10n: zh_CN: Unify Translation of "packfile" l10n: zh_CN: Update Translation: "tag object" |
61d93a2
|
||
mjg |
git-svn: parse authors file more leniently
Currently, git-svn parses an authors file using the perl regex /^(.+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/ in order to extract svn user name, real name and e-mail. This does not match an empty e-mail field like "<>". On the other hand, the output of an authors-prog is parsed with the perl regex /^\s*(.+?)\s*<(.*)>\s*$/ in order to extract real name and e-mail. So, specifying a trivial file grep such as grep "$1" /tmp/authors | head -n 1 | cut -d'=' -f2 | cut -c'2-' as the authors prog gives different results compared to specifying /tmp/authors as the authors file directly. Instead, make git svn uses the perl regex /^(.+?|\(no author\))\s*=\s*(.+?)\s*<(.*)>\s*$/ for parsing the authors file so that the same (slightly more lenient) regex is used in both cases. Reported-by: Till Schäfer <till2.schaefer@tu-dortmund.de> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net> Signed-off-by: Eric Wong <normalperson@yhbt.net> |
f7c6de0
|
||
gitster |
Merge git://bogomips.org/git-svn
* git://bogomips.org/git-svn: git-svn: parse authors file more leniently |
1962994
|
Commits on Sep 11, 2015
asedeno |
Makefile: use SHELL_PATH when running generate-cmdlist.sh
Non-POSIX shells, such as /bin/sh on SunOS, do not support $((...)) arithmetic expansion or $(...) command substitution needed by generate-cmdlist.sh. Make sure that we use a POSIX compliant shell $(SHELL_PATH) when running generate-cmdlist.sh. Signed-off-by: Alejandro R. Sedeño <asedeno@mit.edu> Acked-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
57cee8a
|
||
ralfth |
pull: don't mark values for option "rebase" for translation
"false|true|preserve" are actual values for option "rebase" of the "git-pull" command and should therefore not be marked for translation. Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
7306b39
|
||
ralfth |
tag, update-ref: improve description of option "create-reflog"
The description of option "create-reflog" is "create_reflog", which is neither a good description, nor a sensible string to translate. Change it to a more meaningful message. Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
98c32bd
|
Commits on Sep 13, 2015
andreas-schwab |
Documentation/config: fix formatting for branch.*.rebase and pull.rebase
Don't format the second paragraph as a literal block. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
d238710
|
||
Beat Bolli |
gitk: Adjust the menu line numbers to compensate for the new entry
Commit d835dbb ("gitk: Add a "Copy commit summary" command", 2015-08-13) in the upstream gitk repo added a new context menu entry. Therefore, the line numbers of the entries below the new one need to be adjusted when their text or state is changed. Signed-off-by: Beat Bolli <dev+git@drbeat.li> Cc: Paul Mackerras <paulus@samba.org> Signed-off-by: Paul Mackerras <paulus@samba.org> |
b6f92a8
|
||
Oblomov |
gitk: Accelerators for the main menu
This allows fast, keyboard-only usage of the menu (e.g. Alt+V, N to open a new view). Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com> Signed-off-by: Paul Mackerras <paulus@samba.org> |
d99b4b0
|
Commits on Sep 14, 2015
gitster |
Merge branch 'gb/apply-comment-typofix'
* gb/apply-comment-typofix: apply: comment grammar fix |
e0eeba2
|
||
gitster |
Merge branch 'mp/t7060-diff-index-test'
Fix an old test that was doing the same thing as another one. * mp/t7060-diff-index-test: t7060: actually test "git diff-index --cached -M" |
971f9ea
|
||
gitster |
Merge branch 'jk/pack-protocol-doc'
Streamline documentation of the pkt-line protocol. * jk/pack-protocol-doc: pack-protocol: clarify LF-handling in PKT-LINE() |
4be6af6
|
||
gitster |
Merge git://ozlabs.org/~paulus/gitk
* git://ozlabs.org/~paulus/gitk: gitk: Accelerators for the main menu gitk: Adjust the menu line numbers to compensate for the new entry gitk: Add a "Copy commit summary" command gitk: Update Bulgarian translation (307t) gitk: Update .po files gitk: Update Bulgarian translation (304t) gitk: Use translated version of "Command line" in getcommitlines gitk: Make it easier to go quickly to a specific commit gitk: Show the current view's name in the window title gitk: Add mouse right-click options to copy path and branch name gitk: Remove mc parameter from proc show_error gitk: Fix error when changing colors after closing "List references" window gitk: Replace catch {unset foo} with unset -nocomplain foo gitk: Rearrange window title to be more conventional gitk: sv.po: Update Swedish translation (305t0f0u) gitk: Fix bad English grammar "Matches none Commit Info" |
3f26fe7
|
||
PhilipOakley |
doc: show usage of branch description
The branch description will be included in 'git format-patch --cover-letter' and in 'git pull-request' emails. It can also be used in the automatic merge message. Tell the reader. While here, clarify that the description may be a multi-line explanation of the purpose of the branch's patch series. Signed-off-by: Philip Oakley <philipoakley@iee.org> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
561d2b7
|
||
ethomson |
poll: honor the timeout on Win32
Ensure that when passing a pipe, the gnulib poll replacement will not return 0 before the timeout has passed. Not obeying the timeout (and merely returning 0) causes pathological behavior when preparing a packfile for a repository and taking a long time to do so. If poll were to return 0 immediately, this would cause keep-alives to get sent as quickly as possible until the packfile was created. Such deviance from the standard would cause megabytes (or more) of keep-alive packets to be sent. GetTickCount is used as it is efficient, stable and monotonically increasing. (Neither GetSystemTime nor QueryPerformanceCounter have all three of these properties.) Signed-off-by: Edward Thomson <ethomson@microsoft.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
ef8b53e
|
||
gitster |
Git 2.6-rc2
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
45733fa
|
||
gitster |
Merge branch 'rt/help-strings-fix'
* rt/help-strings-fix: tag, update-ref: improve description of option "create-reflog" pull: don't mark values for option "rebase" for translation |
153ec92
|
||
gitster |
Merge branch 'sg/help-group'
* sg/help-group: Makefile: use SHELL_PATH when running generate-cmdlist.sh |
a9400b0
|
||
gitster |
Merge branch 'ah/show-ref-usage-string'
Both "git show-ref -h" and "git show-ref --help" illustrated that the "--exclude-existing" option makes the command read list of refs from its standard input. Change only the "show-ref -h" output to have a pair of "<>" around the placeholder that designate an input file, i.e. "git show-ref --exclude-existing < <ref-list>". * ah/show-ref-usage-string: show-ref: place angle brackets around variables in usage string |
b8367d1
|
||
gitster |
Merge branch 'js/maint-am-skip-performance-regression'
Recent versions of scripted "git am" has a performance regression in "git am --skip" codepath, which no longer exists in the built-in version on the 'master' front. Fix the regression in the last scripted version that appear in 2.5.x maintenance track and older. * js/maint-am-skip-performance-regression: am --skip/--abort: merge HEAD/ORIG_HEAD tree into index |
cf2094c
|
||
gitster |
Update RelNotes to 2.6 to describe leftover bits since -rc2
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
f4d9753
|
Commits on Sep 16, 2015
Ramsay Jones |
mailmap: update my entry with new email address
My 'demon' email address is no longer functional since, after 16+ years with demon, I have had to change my ISP. :( Also, take the opportunity to remove my middle name, which I only use on official documents (or in the GECOS field when creating a user account on unix). Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
dafc047
|
Commits on Sep 17, 2015
gitster |
Merge branch 'js/maint-am-skip-performance-regression' into maint
* js/maint-am-skip-performance-regression: am --skip/--abort: merge HEAD/ORIG_HEAD tree into index |
02dad26
|
||
gitster |
Merge branch 'ah/submodule-typofix-in-error' into maint
Error string fix. * ah/submodule-typofix-in-error: git-submodule: remove extraneous space from error message |
cfc3e0e
|
||
gitster |
Merge branch 'br/svn-doc-include-paths-config' into maint
* br/svn-doc-include-paths-config: git-svn doc: mention "svn-remote.<name>.include-paths" |
d6579d9
|
||
gitster |
Merge branch 'dt/untracked-subdir' into maint
The experimental untracked-cache feature were buggy when paths with a few levels of subdirectories are involved. * dt/untracked-subdir: untracked cache: fix entry invalidation untracked-cache: fix subdirectory handling t7063: use --force-untracked-cache to speed up a bit untracked-cache: support sparse checkout |
8833ccd
|
||
gitster |
Git 2.5.3
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
ee6ad5f
|
||
gitster |
Merge branch 'as/config-doc-markup-fix'
* as/config-doc-markup-fix: Documentation/config: fix formatting for branch.*.rebase and pull.rebase |
1c1fee7
|
||
gitster |
Merge branch 'et/win32-poll-timeout'
* et/win32-poll-timeout: poll: honor the timeout on Win32 |
8d45eef
|
||
gitster |
Merge branch 'po/doc-branch-desc'
The branch descriptions that are set with "git branch --edit-description" option were used in many places but they weren't clearly documented. * po/doc-branch-desc: doc: show usage of branch description |
a265435
|
||
gitster |
Sync with 2.5.3
* maint: Git 2.5.3 |
4d80024
|
||
gitster |
Update RelNotes to 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
0e57679
|
Commits on Sep 20, 2015
jnavila |
l10n: fr.po v2.6.0 round 1 (2441t)
Signed-off-by: Jean-Noel Avila <jn.avila@free.fr> |
7a43c95
|
||
ralfth |
l10n: de.po: translate 123 new messages
Translate 123 new messages came from git.pot update in df0617b (l10n: git.pot: v2.6.0 round 1 (123 new, 41 removed)). Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com> Acked-by: Phillip Sz <phillip.szelat@gmail.com> Acked-by: Matthias Rüster <matthias.ruester@gmail.com> |
e6e86ed
|
||
jiangxin |
Merge branch 'master' of git://github.com/git-l10n/git-po
* 'master' of git://github.com/git-l10n/git-po: l10n: de.po: translate 123 new messages l10n: fr.po v2.6.0 round 1 (2441t) l10n: sv.po: Update Swedish translation (2441t0f0u) l10n: zh_CN: for git v2.6.0 l10n round 1 l10n: Updated Vietnamese translation (2441t) l10n: git.pot: v2.6.0 round 1 (123 new, 41 removed) l10n: zh_CN: Update Git Glossary: "commit message" l10n: zh_CN: Update Git Glossary: pickaxe l10n: zh_CN: Update Git Glossary: fork l10n: zh_CN: Update Git Glossary: tag l10n: zh_CN: Update Git Glossary: "dumb", "smart" l10n: zh_CN: Update Git Glossary: SHA-1 l10n: zh_CN: Add Surrounding Spaces l10n: zh_CN: Add translations for Git glossary l10n: TEAMS: stash inactive zh_CN team members l10n: zh_CN: Update Translation of "tag" l10n: zh_CN: Unify Translation of "packfile" l10n: zh_CN: Update Translation: "tag object" Signed-off-by: Jiang Xin <worldhello.net@gmail.com> |
070d108
|
||
jiangxin |
l10n: git.pot: v2.6.0 round 2 (3 improvements)
Introduce three i18n improvements from the following commits: * tag, update-ref: improve description of option "create-reflog" * pull: don't mark values for option "rebase" for translation * show-ref: place angle brackets around variables in usage string Signed-off-by: Jiang Xin <worldhello.net@gmail.com> |
80d1b48
|
||
alexhenrie |
l10n: ca.po: update translation
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> |
3ffa1ab
|
||
jiangxin |
l10n: zh_CN: for git v2.6.0 l10n round 2
Update 2 translations (2440t0f0u) for git v2.6.0-rc2. Signed-off-by: Jiang Xin <worldhello.net@gmail.com> |
03ea332
|
||
jnavila |
l10n: fr.po v2.6.0 round 2 (2440t)
Signed-off-by: Jean-Noel Avila <jn.avila@free.fr> |
84486b1
|
||
vnwildman |
l10n: Update and review Vietnamese translation (2440t)
Signed-off-by: Tran Ngoc Quan <vnwildman@gmail.com> |
5fc31c1
|
||
ralfth |
l10n: de.po: translate 2 messages
Translate 2 messages came from git.pot update in e447091 (l10n: git.pot: v2.6.0 round 2 (3 improvements)). Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com> Acked-by: Phillip Sz <phillip.szelat@gmail.com> |
2e0f366
|
||
PhillipSz |
l10n: de.po: better language for one string
Just one string I think we could translate better. Signed-off-by: Phillip Sz <phillip.szelat@gmail.com> Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com> |
18a21c1
|
Commits on Sep 21, 2015
computersforpeace |
send-email: fix uninitialized var warning for $smtp_auth
On the latest version of git-send-email, I see this error just before running SMTP auth (I didn't provide any --smtp-auth= parameter): Use of uninitialized value $smtp_auth in pattern match (m//) at \ /home/briannorris/git/git/git-send-email.perl line 1139. Signed-off-by: Brian Norris <computersforpeace@gmail.com> Reviewed-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> |
904f6e7
|
||
gitster |
Merge tag 'l10n-2.6.0-rnd2+de' of git://github.com/git-l10n/git-po
l10n-2.6.0-rnd2 plus de * tag 'l10n-2.6.0-rnd2+de' of git://github.com/git-l10n/git-po: (25 commits) l10n: de.po: better language for one string l10n: de.po: translate 2 messages l10n: Update and review Vietnamese translation (2440t) l10n: fr.po v2.6.0 round 2 (2440t) l10n: zh_CN: for git v2.6.0 l10n round 2 l10n: ca.po: update translation l10n: git.pot: v2.6.0 round 2 (3 improvements) l10n: de.po: translate 123 new messages l10n: fr.po v2.6.0 round 1 (2441t) l10n: sv.po: Update Swedish translation (2441t0f0u) l10n: zh_CN: for git v2.6.0 l10n round 1 l10n: Updated Vietnamese translation (2441t) l10n: git.pot: v2.6.0 round 1 (123 new, 41 removed) l10n: zh_CN: Update Git Glossary: "commit message" l10n: zh_CN: Update Git Glossary: pickaxe l10n: zh_CN: Update Git Glossary: fork l10n: zh_CN: Update Git Glossary: tag l10n: zh_CN: Update Git Glossary: "dumb", "smart" l10n: zh_CN: Update Git Glossary: SHA-1 l10n: zh_CN: Add Surrounding Spaces ... |
e646ab9
|
||
gitster |
Merge branch 'bn/send-email-smtp-auth-error-message-fix'
Fix a minor regression brought in to "git send-email" by a recent addition of the "--smtp-auth" option. * bn/send-email-smtp-auth-error-message-fix: send-email: fix uninitialized var warning for $smtp_auth |
b6bd2d0
|
||
gitster |
Merge branch 'rj/mailmap-ramsay'
* rj/mailmap-ramsay: mailmap: update my entry with new email address |
74a844a
|
||
gitster |
Git 2.6-rc3
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
8d530c4
|
Commits on Sep 28, 2015
gitster |
Git 2.6
Signed-off-by: Junio C Hamano <gitster@pobox.com> |
be08dee
|
Unified
Split
Showing
with
6,102 additions
and 2,583 deletions.
- +1 −0 .gitignore
- +1 −1 .mailmap
- +9 −0 Documentation/RelNotes/2.2.3.txt
- +9 −0 Documentation/RelNotes/2.3.9.txt
- +21 −0 Documentation/RelNotes/2.4.8.txt
- +9 −0 Documentation/RelNotes/2.4.9.txt
- +65 −0 Documentation/RelNotes/2.5.1.txt
- +63 −0 Documentation/RelNotes/2.5.2.txt
- +17 −0 Documentation/RelNotes/2.5.3.txt
- +370 −0 Documentation/RelNotes/2.6.0.txt
- +154 −37 Documentation/config.txt
- +5 −2 Documentation/git-am.txt
- +73 −60 Documentation/git-bisect.txt
- +3 −1 Documentation/git-branch.txt
- +14 −0 Documentation/git-cat-file.txt
- +2 −2 Documentation/git-check-ref-format.txt
- +15 −0 Documentation/git-checkout.txt
- +7 −3 Documentation/git-config.txt
- +2 −2 Documentation/git-describe.txt
- +33 −6 Documentation/git-fast-import.txt
- +1 −1 Documentation/git-format-patch.txt
- +6 −1 Documentation/git-fsck.txt
- +6 −0 Documentation/git-log.txt
- +1 −1 Documentation/git-merge.txt
- +22 −3 Documentation/git-notes.txt
- +10 −5 Documentation/git-push.txt
- +16 −0 Documentation/git-rebase.txt
- +4 −0 Documentation/git-reflog.txt
- +2 −1 Documentation/git-request-pull.txt
- +2 −2 Documentation/git-rev-parse.txt
- +19 −6 Documentation/git-send-email.txt
- +15 −1 Documentation/git-send-pack.txt
- +3 −0 Documentation/git-svn.txt
- +4 −2 Documentation/git-tag.txt
- +8 −116 Documentation/git-tools.txt
- +4 −1 Documentation/git-update-ref.txt
- +4 −0 Documentation/git-verify-commit.txt
- +4 −0 Documentation/git-verify-tag.txt
- +24 −24 Documentation/git-worktree.txt
- +30 −7 Documentation/git.txt
- +2 −0 Documentation/gitattributes.txt
- +3 −0 Documentation/gitremote-helpers.txt
- +11 −11 Documentation/gitrepository-layout.txt
- +21 −0 Documentation/glossary-content.txt
- +23 −10 Documentation/i18n.txt
- +2 −0 Documentation/pretty-formats.txt
- +2 −0 Documentation/pretty-options.txt
- +7 −0 Documentation/rev-list-options.txt
- +3 −0 Documentation/technical/api-argv-array.txt
- +0 −220 Documentation/technical/api-lockfile.txt
- +19 −0 Documentation/technical/api-parse-options.txt
- +62 −0 Documentation/technical/api-submodule-config.txt
- +1 −1 Documentation/technical/index-format.txt
- +26 −20 Documentation/technical/pack-protocol.txt
- +4 −1 Documentation/technical/protocol-common.txt
- +1 −3 GIT-VERSION-GEN
- +8 −4 Makefile
- +1 −1 RelNotes
- +8 −0 advice.c
- +1 −0 advice.h
- +2 −1 alias.c
- +94 −5 archive-zip.c
- +2 −1 archive.c
- +6 −0 argv-array.c
- +1 −0 argv-array.h
- +3 −1 attr.c
- +78 −47 bisect.c
- +2 −0 bisect.h
- +96 −7 branch.c
- +15 −0 branch.h
- +2 −0 builtin.h
- +0 −2 builtin/add.c
- +2,411 −0 builtin/am.c
- +1 −1 builtin/apply.c
- +12 −9 builtin/blame.c
- +4 −3 builtin/branch.c
- +97 −35 builtin/cat-file.c
- +18 −89 builtin/checkout.c
- +26 −4 builtin/clean.c
- +97 −29 builtin/clone.c
- +27 −28 builtin/commit.c
- +41 −45 builtin/config.c
- +4 −4 builtin/describe.c
- +1 −0 builtin/fast-export.c
- +26 −18 builtin/fetch.c
- +1 −0 builtin/fmt-merge-msg.c
- +19 −1,094 builtin/for-each-ref.c
- +56 −26 builtin/fsck.c
- +11 −23 builtin/gc.c
- +11 −6 builtin/index-pack.c
- +2 −1 builtin/init-db.c
- +32 −8 builtin/log.c
- +1 −1 builtin/ls-files.c
- +15 −15 builtin/merge.c
- +36 −13 builtin/notes.c
- +6 −23 builtin/pack-objects.c
- +887 −0 builtin/pull.c
- +41 −1 builtin/push.c
- +1 −1 builtin/read-tree.c
- +27 −3 builtin/receive-pack.c
- +33 −2 builtin/reflog.c
- +5 −35 builtin/remote.c
- +13 −11 builtin/repack.c
- +3 −3 builtin/replace.c
- +9 −9 builtin/rerere.c
- +1 −1 builtin/reset.c
- +3 −0 builtin/rev-list.c
- +30 −27 builtin/rev-parse.c
- +88 −103 builtin/send-pack.c
- +1 −1 builtin/shortlog.c
- +6 −3 builtin/show-branch.c
- +1 −1 builtin/show-ref.c
- +4 −1 builtin/tag.c
- +11 −5 builtin/unpack-objects.c
- +28 −7 builtin/update-ref.c
- +13 −12 builtin/verify-commit.c
- +22 −8 builtin/verify-tag.c
- +87 −44 builtin/worktree.c
- +16 −10 bundle.c
- +17 −12 cache-tree.c
- +1 −0 cache-tree.h
- +86 −89 cache.h
- +29 −5 commit-slab.h
- +26 −23 commit.c
- +2 −2 commit.h
- +1 −1 compat/mingw.c
- +14 −2 compat/poll/poll.c
- +43 −21 config.c
- +9 −13 contrib/completion/git-completion.bash
- +1 −1 contrib/completion/git-prompt.sh
- +2 −2 contrib/examples/builtin-fetch--tool.c
- +8 −6 { → contrib/examples}/git-am.sh
- +1 −1 { → contrib/examples}/git-pull.sh
- +1 −1 contrib/subtree/git-subtree.sh
- +4 −0 contrib/subtree/t/t7900-subtree.sh
- +6 −19 credential-cache--daemon.c
- +1 −1 credential-store.c
- +1 −1 daemon.c
View
1
.gitignore
@@ -205,6 +205,7 @@ | ||
/test-sha1-array | ||
/test-sigchain | ||
/test-string-list | ||
+/test-submodule-config | ||
/test-subprocess | ||
/test-svn-fe | ||
/test-urlmatch-normalization | ||
View
2
.mailmap
@@ -186,7 +186,7 @@ Philip Jägenstedt <philip@foolip.org> <philip.jagenstedt@gmail.com> | ||
Philipp A. Hartmann <pah@qo.cx> <ph@sorgh.de> | ||
Philippe Bruhat <book@cpan.org> | ||
Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com> | ||
-Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk> | ||
+Ramsay Jones <ramsay@ramsayjones.plus.com> <ramsay@ramsay1.demon.co.uk> | ||
René Scharfe <l.s.r@web.de> <rene.scharfe@lsrfire.ath.cx> | ||
Robert Fitzsimons <robfitz@273k.net> | ||
Robert Shearman <robertshearman@gmail.com> <rob@codeweavers.com> | ||
View
9
Documentation/RelNotes/2.2.3.txt
@@ -0,0 +1,9 @@ | ||
+Git v2.2.3 Release Notes | ||
+======================== | ||
+ | ||
+Fixes since v2.2.2 | ||
+------------------ | ||
+ | ||
+ * A handful of codepaths that used to use fixed-sized arrays to hold | ||
+ pathnames have been corrected to use strbuf and other mechanisms to | ||
+ allow longer pathnames without fearing overflows. |
View
9
Documentation/RelNotes/2.3.9.txt
@@ -0,0 +1,9 @@ | ||
+Git v2.3.9 Release Notes | ||
+======================== | ||
+ | ||
+Fixes since v2.3.8 | ||
+------------------ | ||
+ | ||
+ * A handful of codepaths that used to use fixed-sized arrays to hold | ||
+ pathnames have been corrected to use strbuf and other mechanisms to | ||
+ allow longer pathnames without fearing overflows. |
View
21
Documentation/RelNotes/2.4.8.txt
@@ -0,0 +1,21 @@ | ||
+Git v2.4.8 Release Notes | ||
+======================== | ||
+ | ||
+Fixes since v2.4.7 | ||
+------------------ | ||
+ | ||
+ * Abandoning an already applied change in "git rebase -i" with | ||
+ "--continue" left CHERRY_PICK_HEAD and confused later steps. | ||
+ | ||
+ * Various fixes around "git am" that applies a patch to a history | ||
+ that is not there yet. | ||
+ | ||
+ * "git for-each-ref" reported "missing object" for 0{40} when it | ||
+ encounters a broken ref. The lack of object whose name is 0{40} is | ||
+ not the problem; the ref being broken is. | ||
+ | ||
+ * "git commit --cleanup=scissors" was not careful enough to protect | ||
+ against getting fooled by a line that looked like scissors. | ||
+ | ||
+Also contains typofixes, documentation updates and trivial code | ||
+clean-ups. |
View
9
Documentation/RelNotes/2.4.9.txt
@@ -0,0 +1,9 @@ | ||
+Git v2.4.9 Release Notes | ||
+======================== | ||
+ | ||
+Fixes since v2.4.9 | ||
+------------------ | ||
+ | ||
+ * A handful of codepaths that used to use fixed-sized arrays to hold | ||
+ pathnames have been corrected to use strbuf and other mechanisms to | ||
+ allow longer pathnames without fearing overflows. |
View
65
Documentation/RelNotes/2.5.1.txt
@@ -0,0 +1,65 @@ | ||
+Git v2.5.1 Release Notes | ||
+======================== | ||
+ | ||
+Fixes since v2.5 | ||
+---------------- | ||
+ | ||
+ * Running an aliased command from a subdirectory when the .git thing | ||
+ in the working tree is a gitfile pointing elsewhere did not work. | ||
+ | ||
+ * Often a fast-import stream builds a new commit on top of the | ||
+ previous commit it built, and it often unconditionally emits a | ||
+ "from" command to specify the first parent, which can be omitted in | ||
+ such a case. This caused fast-import to forget the tree of the | ||
+ previous commit and then re-read it from scratch, which was | ||
+ inefficient. Optimize for this common case. | ||
+ | ||
+ * The "rev-parse --parseopt" mode parsed the option specification | ||
+ and the argument hint in a strange way to allow '=' and other | ||
+ special characters in the option name while forbidding them from | ||
+ the argument hint. This made it impossible to define an option | ||
+ like "--pair <key>=<value>" with "pair=key=value" specification, | ||
+ which instead would have defined a "--pair=key <value>" option. | ||
+ | ||
+ * A "rebase" replays changes of the local branch on top of something | ||
+ else, as such they are placed in stage #3 and referred to as | ||
+ "theirs", while the changes in the new base, typically a foreign | ||
+ work, are placed in stage #2 and referred to as "ours". Clarify | ||
+ the "checkout --ours/--theirs". | ||
+ | ||
+ * An experimental "untracked cache" feature used uname(2) in a | ||
+ slightly unportable way. | ||
+ | ||
+ * "sparse checkout" misbehaved for a path that is excluded from the | ||
+ checkout when switching between branches that differ at the path. | ||
+ | ||
+ * The low-level "git send-pack" did not honor 'user.signingkey' | ||
+ configuration variable when sending a signed-push. | ||
+ | ||
+ * An attempt to delete a ref by pushing into a repository whose HEAD | ||
+ symbolic reference points at an unborn branch that cannot be | ||
+ created due to ref D/F conflict (e.g. refs/heads/a/b exists, HEAD | ||
+ points at refs/heads/a) failed. | ||
+ | ||
+ * "git subtree" (in contrib/) depended on "git log" output to be | ||
+ stable, which was a no-no. Apply a workaround to force a | ||
+ particular date format. | ||
+ | ||
+ * "git clone $URL" in recent releases of Git contains a regression in | ||
+ the code that invents a new repository name incorrectly based on | ||
+ the $URL. This has been corrected. | ||
+ (merge db2e220 jk/guess-repo-name-regression-fix later to maint). | ||
+ | ||
+ * Running tests with the "-x" option to make them verbose had some | ||
+ unpleasant interactions with other features of the test suite. | ||
+ (merge 9b5fe78 jk/test-with-x later to maint). | ||
+ | ||
+ * "git pull" in recent releases of Git has a regression in the code | ||
+ that allows custom path to the --upload-pack=<program>. This has | ||
+ been corrected. | ||
+ | ||
+ * pipe() emulation used in Git for Windows looked at a wrong variable | ||
+ when checking for an error from an _open_osfhandle() call. | ||
+ | ||
+Also contains typofixes, documentation updates and trivial code | ||
+clean-ups. |
View
63
Documentation/RelNotes/2.5.2.txt
@@ -0,0 +1,63 @@ | ||
+Git v2.5.2 Release Notes | ||
+======================== | ||
+ | ||
+Fixes since v2.5.1 | ||
+------------------ | ||
+ | ||
+ * "git init empty && git -C empty log" said "bad default revision 'HEAD'", | ||
+ which was found to be a bit confusing to new users. | ||
+ | ||
+ * The "interpret-trailers" helper mistook a multi-paragraph title of | ||
+ a commit log message with a colon in it as the end of the trailer | ||
+ block. | ||
+ | ||
+ * When re-priming the cache-tree opportunistically while committing | ||
+ the in-core index as-is, we mistakenly invalidated the in-core | ||
+ index too aggressively, causing the experimental split-index code | ||
+ to unnecessarily rewrite the on-disk index file(s). | ||
+ | ||
+ * "git archive" did not use zip64 extension when creating an archive | ||
+ with more than 64k entries, which nobody should need, right ;-)? | ||
+ | ||
+ * The code in "multiple-worktree" support that attempted to recover | ||
+ from an inconsistent state updated an incorrect file. | ||
+ | ||
+ * "git rev-list" does not take "--notes" option, but did not complain | ||
+ when one is given. | ||
+ | ||
+ * Because the configuration system does not allow "alias.0foo" and | ||
+ "pager.0foo" as the configuration key, the user cannot use '0foo' | ||
+ as a custom command name anyway, but "git 0foo" tried to look these | ||
+ keys up and emitted useless warnings before saying '0foo is not a | ||
+ git command'. These warning messages have been squelched. | ||
+ | ||
+ * We recently rewrote one of the build scripts in Perl, which made it | ||
+ necessary to have Perl to build Git. Reduced Perl dependency by | ||
+ rewriting it again using sed. | ||
+ | ||
+ * t1509 test that requires a dedicated VM environment had some | ||
+ bitrot, which has been corrected. | ||
+ | ||
+ * strbuf_read() used to have one extra iteration (and an unnecessary | ||
+ strbuf_grow() of 8kB), which was eliminated. | ||
+ | ||
+ * The codepath to produce error messages had a hard-coded limit to | ||
+ the size of the message, primarily to avoid memory allocation while | ||
+ calling die(). | ||
+ | ||
+ * When trying to see that an object does not exist, a state errno | ||
+ leaked from our "first try to open a packfile with O_NOATIME and | ||
+ then if it fails retry without it" logic on a system that refuses | ||
+ O_NOATIME. This confused us and caused us to die, saying that the | ||
+ packfile is unreadable, when we should have just reported that the | ||
+ object does not exist in that packfile to the caller. | ||
+ | ||
+ * An off-by-one error made "git remote" to mishandle a remote with a | ||
+ single letter nickname. | ||
+ | ||
+ * A handful of codepaths that used to use fixed-sized arrays to hold | ||
+ pathnames have been corrected to use strbuf and other mechanisms to | ||
+ allow longer pathnames without fearing overflows. | ||
+ | ||
+Also contains typofixes, documentation updates and trivial code | ||
+clean-ups. |
View
17
Documentation/RelNotes/2.5.3.txt
@@ -0,0 +1,17 @@ | ||
+Git v2.5.3 Release Notes | ||
+======================== | ||
+ | ||
+Fixes since v2.5.2 | ||
+------------------ | ||
+ | ||
+ * The experimental untracked-cache feature were buggy when paths with | ||
+ a few levels of subdirectories are involved. | ||
+ | ||
+ * Recent versions of scripted "git am" has a performance regression | ||
+ in "git am --skip" codepath, which no longer exists in the | ||
+ built-in version on the 'master' front. Fix the regression in | ||
+ the last scripted version that appear in 2.5.x maintenance track | ||
+ and older. | ||
+ | ||
+Also contains typofixes, documentation updates and trivial code | ||
+clean-ups. |
View
370
Documentation/RelNotes/2.6.0.txt
@@ -0,0 +1,370 @@ | ||
+Git 2.6 Release Notes | ||
+===================== | ||
+ | ||
+Updates since v2.5 | ||
+------------------ | ||
+ | ||
+UI, Workflows & Features | ||
+ | ||
+ * An asterisk as a substring (as opposed to the entirety) of a path | ||
+ component for both side of a refspec, e.g. | ||
+ "refs/heads/o*:refs/remotes/heads/i*", is now allowed. | ||
+ | ||
+ * New userdiff pattern definition for fountain screenwriting markup | ||
+ format has been added. | ||
+ | ||
+ * "git log" and friends learned a new "--date=format:..." option to | ||
+ format timestamps using system's strftime(3). | ||
+ | ||
+ * "git fast-import" learned to respond to the get-mark command via | ||
+ its cat-blob-fd interface. | ||
+ | ||
+ * "git rebase -i" learned "drop commit-object-name subject" command | ||
+ as another way to skip replaying of a commit. | ||
+ | ||
+ * A new configuration variable can enable "--follow" automatically | ||
+ when "git log" is run with one pathspec argument. | ||
+ | ||
+ * "git status" learned to show a more detailed information regarding | ||
+ the "rebase -i" session in progress. | ||
+ | ||
+ * "git cat-file" learned "--batch-all-objects" option to enumerate all | ||
+ available objects in the repository more quickly than "rev-list | ||
+ --all --objects" (the output includes unreachable objects, though). | ||
+ | ||
+ * "git fsck" learned to ignore errors on a set of known-to-be-bad | ||
+ objects, and also allows the warning levels of various kinds of | ||
+ non-critical breakages to be tweaked. | ||
+ | ||
+ * "git rebase -i"'s list of todo is made configurable. | ||
+ | ||
+ * "git send-email" now performs alias-expansion on names that are | ||
+ given via --cccmd, etc. | ||
+ | ||
+ * An environment variable GIT_REPLACE_REF_BASE tells Git to look into | ||
+ refs hierarchy other than refs/replace/ for the object replacement | ||
+ data. | ||
+ | ||
+ * Allow untracked cache (experimental) to be used when sparse | ||
+ checkout (experimental) is also in use. | ||
+ | ||
+ * "git pull --rebase" has been taught to pay attention to | ||
+ rebase.autostash configuration. | ||
+ | ||
+ * The command-line completion script (in contrib/) has been updated. | ||
+ | ||
+ * A negative !ref entry in multi-value transfer.hideRefs | ||
+ configuration can be used to say "don't hide this one". | ||
+ | ||
+ * After "git am" without "-3" stops, running "git am -3" pays attention | ||
+ to "-3" only for the patch that caused the original invocation | ||
+ to stop. | ||
+ | ||
+ * When linked worktree is used, simultaneous "notes merge" instances | ||
+ for the same ref in refs/notes/* are prevented from stomping on | ||
+ each other. | ||
+ | ||
+ * "git send-email" learned a new option --smtp-auth to limit the SMTP | ||
+ AUTH mechanisms to be used to a subset of what the system library | ||
+ supports. | ||
+ | ||
+ * A new configuration variable http.sslVersion can be used to specify | ||
+ what specific version of SSL/TLS to use to make a connection. | ||
+ | ||
+ * "git notes merge" can be told with "--strategy=<how>" option how to | ||
+ automatically handle conflicts; this can now be configured by | ||
+ setting notes.mergeStrategy configuration variable. | ||
+ | ||
+ * "git log --cc" did not show any patch, even though most of the time | ||
+ the user meant "git log --cc -p -m" to see patch output for commits | ||
+ with a single parent, and combined diff for merge commits. The | ||
+ command is taught to DWIM "--cc" (without "--raw" and other forms | ||
+ of output specification) to "--cc -p -m". | ||
+ | ||
+ * "git config --list" output was hard to parse when values consist of | ||
+ multiple lines. "--name-only" option is added to help this. | ||
+ | ||
+ * A handful of usability & cosmetic fixes to gitk and l10n updates. | ||
+ | ||
+ * A completely empty e-mail address <> is now allowed in the authors | ||
+ file used by git-svn, to match the way it accepts the output from | ||
+ authors-prog. | ||
+ | ||
+ | ||
+Performance, Internal Implementation, Development Support etc. | ||
+ | ||
+ * In preparation for allowing different "backends" to store the refs | ||
+ in a way different from the traditional "one ref per file in | ||
+ $GIT_DIR or in a $GIT_DIR/packed-refs file" filesystem storage, | ||
+ direct filesystem access to ref-like things like CHERRY_PICK_HEAD | ||
+ from scripts and programs has been reduced. | ||
+ | ||
+ * Computation of untracked status indicator by bash prompt | ||
+ script (in contrib/) has been optimized. | ||
+ | ||
+ * Memory use reduction when commit-slab facility is used to annotate | ||
+ sparsely (which is not recommended in the first place). | ||
+ | ||
+ * Clean up refs API and make "git clone" less intimate with the | ||
+ implementation detail. | ||
+ | ||
+ * "git pull" was reimplemented in C. | ||
+ | ||
+ * The packet tracing machinery allows to capture an incoming pack | ||
+ data to a file for debugging. | ||
+ | ||
+ * Move machinery to parse human-readable scaled numbers like 1k, 4M, | ||
+ and 2G as an option parameter's value from pack-objects to | ||
+ parse-options API, to make it available to other codepaths. | ||
+ | ||
+ * "git verify-tag" and "git verify-commit" have been taught to share | ||
+ more code, and then learned to optionally show the verification | ||
+ message from the underlying GPG implementation. | ||
+ | ||
+ * Various enhancements around "git am" reading patches generated by | ||
+ foreign SCM have been made. | ||
+ | ||
+ * Ref listing by "git branch -l" and "git tag -l" commands has | ||
+ started to be rebuilt, based on the for-each-ref machinery. | ||
+ | ||
+ * The code to perform multi-tree merges has been taught to repopulate | ||
+ the cache-tree upon a successful merge into the index, so that | ||
+ subsequent "diff-index --cached" (hence "status") and "write-tree" | ||
+ (hence "commit") will go faster. | ||
+ | ||
+ The same logic in "git checkout" may now be removed, but that is a | ||
+ separate issue. | ||
+ | ||
+ * Tests that assume how reflogs are represented on the filesystem too | ||
+ much have been corrected. | ||
+ | ||
+ * "git am" has been rewritten in "C". | ||
+ | ||
+ * git_path() and mkpath() are handy helper functions but it is easy | ||
+ to misuse, as the callers need to be careful to keep the number of | ||
+ active results below 4. Their uses have been reduced. | ||
+ | ||
+ * The "lockfile" API has been rebuilt on top of a new "tempfile" API. | ||
+ | ||
+ * To prepare for allowing a different "ref" backend to be plugged in | ||
+ to the system, update_ref()/delete_ref() have been taught about | ||
+ ref-like things like MERGE_HEAD that are per-worktree (they will | ||
+ always be written to the filesystem inside $GIT_DIR). | ||
+ | ||
+ * The gitmodules API that is accessed from the C code learned to | ||
+ cache stuff lazily. | ||
+ | ||
+ | ||
+Also contains various documentation updates and code clean-ups. | ||
+ | ||
+ | ||
+Fixes since v2.5 | ||
+---------------- | ||
+ | ||
+Unless otherwise noted, all the fixes since v2.5 in the maintenance | ||
+track are contained in this release (see the maintenance releases' | ||
+notes for details). | ||
+ | ||
+ * "git subtree" (in contrib/) depended on "git log" output to be | ||
+ stable, which was a no-no. Apply a workaround to force a | ||
+ particular date format. | ||
+ (merge e7aac44 da/subtree-date-confusion later to maint). | ||
+ | ||
+ * An attempt to delete a ref by pushing into a repository whose HEAD | ||
+ symbolic reference points at an unborn branch that cannot be | ||
+ created due to ref D/F conflict (e.g. refs/heads/a/b exists, HEAD | ||
+ points at refs/heads/a) failed. | ||
+ (merge b112b14 jx/do-not-crash-receive-pack-wo-head later to maint). | ||
+ | ||
+ * The low-level "git send-pack" did not honor 'user.signingkey' | ||
+ configuration variable when sending a signed-push. | ||
+ (merge d830d39 db/send-pack-user-signingkey later to maint). | ||
+ | ||
+ * "sparse checkout" misbehaved for a path that is excluded from the | ||
+ checkout when switching between branches that differ at the path. | ||
+ (merge 7d78241 as/sparse-checkout-removal later to maint). | ||
+ | ||
+ * An experimental "untracked cache" feature used uname(2) in a | ||
+ slightly unportable way. | ||
+ (merge 100e433 cb/uname-in-untracked later to maint). | ||
+ | ||
+ * A "rebase" replays changes of the local branch on top of something | ||
+ else, as such they are placed in stage #3 and referred to as | ||
+ "theirs", while the changes in the new base, typically a foreign | ||
+ work, are placed in stage #2 and referred to as "ours". Clarify | ||
+ the "checkout --ours/--theirs". | ||
+ (merge f303016 se/doc-checkout-ours-theirs later to maint). | ||
+ | ||
+ * The "rev-parse --parseopt" mode parsed the option specification | ||
+ and the argument hint in a strange way to allow '=' and other | ||
+ special characters in the option name while forbidding them from | ||
+ the argument hint. This made it impossible to define an option | ||
+ like "--pair <key>=<value>" with "pair=key=value" specification, | ||
+ which instead would have defined a "--pair=key <value>" option. | ||
+ (merge 2d893df ib/scripted-parse-opt-better-hint-string later to maint). | ||
+ | ||
+ * Often a fast-import stream builds a new commit on top of the | ||
+ previous commit it built, and it often unconditionally emits a | ||
+ "from" command to specify the first parent, which can be omitted in | ||
+ such a case. This caused fast-import to forget the tree of the | ||
+ previous commit and then re-read it from scratch, which was | ||
+ inefficient. Optimize for this common case. | ||
+ (merge 0df3245 mh/fast-import-optimize-current-from later to maint). | ||
+ | ||
+ * Running an aliased command from a subdirectory when the .git thing | ||
+ in the working tree is a gitfile pointing elsewhere did not work. | ||
+ (merge d95138e nd/export-worktree later to maint). | ||
+ | ||
+ * "Is this subdirectory a separate repository that should not be | ||
+ touched?" check "git clean" was inefficient. This was replaced | ||
+ with a more optimized check. | ||
+ (merge fbf2fec ee/clean-remove-dirs later to maint). | ||
+ | ||
+ * The "new-worktree-mode" hack in "checkout" that was added in | ||
+ nd/multiple-work-trees topic has been removed by updating the | ||
+ implementation of new "worktree add". | ||
+ (merge 65f9b75 es/worktree-add-cleanup later to maint). | ||
+ | ||
+ * Remove remaining cruft from "git checkout --to", which | ||
+ transitioned to "git worktree add". | ||
+ (merge 114ff88 es/worktree-add later to maint). | ||
+ | ||
+ * An off-by-one error made "git remote" to mishandle a remote with a | ||
+ single letter nickname. | ||
+ (merge bc598c3 mh/get-remote-group-fix later to maint). | ||
+ | ||
+ * "git clone $URL", when cloning from a site whose sole purpose is to | ||
+ host a single repository (hence, no path after <scheme>://<site>/), | ||
+ tried to use the site name as the new repository name, but did not | ||
+ remove username or password when <site> part was of the form | ||
+ <user>@<pass>:<host>. The code is taught to redact these. | ||
+ (merge adef956 ps/guess-repo-name-at-root later to maint). | ||
+ | ||
+ * Running tests with the "-x" option to make them verbose had some | ||
+ unpleasant interactions with other features of the test suite. | ||
+ (merge 9b5fe78 jk/test-with-x later to maint). | ||
+ | ||
+ * t1509 test that requires a dedicated VM environment had some | ||
+ bitrot, which has been corrected. | ||
+ (merge faacc5a ps/t1509-chroot-test-fixup later to maint). | ||
+ | ||
+ * "git pull" in recent releases of Git has a regression in the code | ||
+ that allows custom path to the --upload-pack=<program>. This has | ||
+ been corrected. | ||
+ | ||
+ Note that this is irrelevant for 'master' with "git pull" rewritten | ||
+ in C. | ||
+ (merge 13e0e28 mm/pull-upload-pack later to maint). | ||
+ | ||
+ * When trying to see that an object does not exist, a state errno | ||
+ leaked from our "first try to open a packfile with O_NOATIME and | ||
+ then if it fails retry without it" logic on a system that refuses | ||
+ O_NOATIME. This confused us and caused us to die, saying that the | ||
+ packfile is unreadable, when we should have just reported that the | ||
+ object does not exist in that packfile to the caller. | ||
+ (merge dff6f28 cb/open-noatime-clear-errno later to maint). | ||
+ | ||
+ * The codepath to produce error messages had a hard-coded limit to | ||
+ the size of the message, primarily to avoid memory allocation while | ||
+ calling die(). | ||
+ (merge f4c3edc jk/long-error-messages later to maint). | ||
+ | ||
+ * strbuf_read() used to have one extra iteration (and an unnecessary | ||
+ strbuf_grow() of 8kB), which was eliminated. | ||
+ (merge 3ebbd00 jh/strbuf-read-use-read-in-full later to maint). | ||
+ | ||
+ * We rewrote one of the build scripts in Perl but this reimplements | ||
+ in Bourne shell. | ||
+ (merge 57cee8a sg/help-group later to maint). | ||
+ | ||
+ * The experimental untracked-cache feature were buggy when paths with | ||
+ a few levels of subdirectories are involved. | ||
+ (merge 73f9145 dt/untracked-subdir later to maint). | ||
+ | ||
+ * "interpret-trailers" helper mistook a single-liner log message that | ||
+ has a colon as the end of existing trailer. | ||
+ | ||
+ * The "interpret-trailers" helper mistook a multi-paragraph title of | ||
+ a commit log message with a colon in it as the end of the trailer | ||
+ block. | ||
+ (merge 5c99995 cc/trailers-corner-case-fix later to maint). | ||
+ | ||
+ * "git describe" without argument defaulted to describe the HEAD | ||
+ commit, but "git describe --contains" didn't. Arguably, in a | ||
+ repository used for active development, such defaulting would not | ||
+ be very useful as the tip of branch is typically not tagged, but it | ||
+ is better to be consistent. | ||
+ (merge 2bd0706 sg/describe-contains later to maint). | ||
+ | ||
+ * The client side codepaths in "git push" have been cleaned up | ||
+ and the user can request to perform an optional "signed push", | ||
+ i.e. sign only when the other end accepts signed push. | ||
+ (merge 68c757f db/push-sign-if-asked later to maint). | ||
+ | ||
+ * Because the configuration system does not allow "alias.0foo" and | ||
+ "pager.0foo" as the configuration key, the user cannot use '0foo' | ||
+ as a custom command name anyway, but "git 0foo" tried to look these | ||
+ keys up and emitted useless warnings before saying '0foo is not a | ||
+ git command'. These warning messages have been squelched. | ||
+ (merge 9e9de18 jk/fix-alias-pager-config-key-warnings later to maint). | ||
+ | ||
+ * "git rev-list" does not take "--notes" option, but did not complain | ||
+ when one is given. | ||
+ (merge 2aea7a5 jk/rev-list-has-no-notes later to maint). | ||
+ | ||
+ * When re-priming the cache-tree opportunistically while committing | ||
+ the in-core index as-is, we mistakenly invalidated the in-core | ||
+ index too aggressively, causing the experimental split-index code | ||
+ to unnecessarily rewrite the on-disk index file(s). | ||
+ (merge 475a344 dt/commit-preserve-base-index-upon-opportunistic-cache-tree-update later to maint). | ||
+ | ||
+ * "git archive" did not use zip64 extension when creating an archive | ||
+ with more than 64k entries, which nobody should need, right ;-)? | ||
+ (merge 88329ca rs/archive-zip-many later to maint). | ||
+ | ||
+ * The code in "multiple-worktree" support that attempted to recover | ||
+ from an inconsistent state updated an incorrect file. | ||
+ (merge 82fde87 nd/fixup-linked-gitdir later to maint). | ||
+ | ||
+ * On case insensitive systems, "git p4" did not work well with client | ||
+ specs. | ||
+ | ||
+ * "git init empty && git -C empty log" said "bad default revision 'HEAD'", | ||
+ which was found to be a bit confusing to new users. | ||
+ (merge ce11360 jk/log-missing-default-HEAD later to maint). | ||
+ | ||
+ * Recent versions of scripted "git am" has a performance regression in | ||
+ "git am --skip" codepath, which no longer exists in the built-in | ||
+ version on the 'master' front. Fix the regression in the last | ||
+ scripted version that appear in 2.5.x maintenance track and older. | ||
+ (merge b9d6689 js/maint-am-skip-performance-regression later to maint). | ||
+ | ||
+ * The branch descriptions that are set with "git branch --edit-description" | ||
+ option were used in many places but they weren't clearly documented. | ||
+ (merge 561d2b7 po/doc-branch-desc later to maint). | ||
+ | ||
+ * Code cleanups and documentation updates. | ||
+ (merge 1c601af es/doc-clean-outdated-tools later to maint). | ||
+ (merge 3581304 kn/tag-doc-fix later to maint). | ||
+ (merge 3a59e59 kb/i18n-doc later to maint). | ||
+ (merge 45abdee sb/remove-unused-var-from-builtin-add later to maint). | ||
+ (merge 14691e3 sb/parse-options-codeformat later to maint). | ||
+ (merge 4a6ada3 ad/bisect-cleanup later to maint). | ||
+ (merge da4c5ad ta/docfix-index-format-tech later to maint). | ||
+ (merge ae25fd3 sb/check-return-from-read-ref later to maint). | ||
+ (merge b3325df nd/dwim-wildcards-as-pathspecs later to maint). | ||
+ (merge 7aa9b9b sg/wt-status-header-inclusion later to maint). | ||
+ (merge f04c690 as/docfix-reflog-expire-unreachable later to maint). | ||
+ (merge 1269847 sg/t3020-typofix later to maint). | ||
+ (merge 8b54c23 jc/calloc-pathspec later to maint). | ||
+ (merge a6926b8 po/po-readme later to maint). | ||
+ (merge 54d160e ss/fix-config-fd-leak later to maint). | ||
+ (merge b80fa84 ah/submodule-typofix-in-error later to maint). | ||
+ (merge 99885bc ah/reflog-typofix-in-error later to maint). | ||
+ (merge 9476c2c ah/read-tree-usage-string later to maint). | ||
+ (merge b8c1d27 ah/pack-objects-usage-strings later to maint). | ||
+ (merge 486e1e1 br/svn-doc-include-paths-config later to maint). | ||
+ (merge 1733ed3 ee/clean-test-fixes later to maint). | ||
+ (merge 5fcadc3 gb/apply-comment-typofix later to maint). | ||
+ (merge b894d3e mp/t7060-diff-index-test later to maint). | ||
+ (merge d238710 as/config-doc-markup-fix later to maint). |
View
191
Documentation/config.txt
@@ -769,6 +769,14 @@ am.keepcr:: | ||
by giving '--no-keep-cr' from the command line. | ||
See linkgit:git-am[1], linkgit:git-mailsplit[1]. | ||
+am.threeWay:: | ||
+ By default, `git am` will fail if the patch does not apply cleanly. When | ||
+ set to true, this setting tells `git am` to fall back on 3-way merge if | ||
+ the patch records the identity of blobs it is supposed to apply to and | ||
+ we have those blobs available locally (equivalent to giving the `--3way` | ||
+ option from the command line). Defaults to `false`. | ||
+ See linkgit:git-am[1]. | ||
+ | ||
apply.ignoreWhitespace:: | ||
When set to 'change', tells 'git apply' to ignore changes in | ||
whitespace, in the same way as the '--ignore-space-change' | ||
@@ -858,9 +866,9 @@ branch.<name>.rebase:: | ||
"git pull" is run. See "pull.rebase" for doing this in a non | ||
branch-specific manner. | ||
+ | ||
- When preserve, also pass `--preserve-merges` along to 'git rebase' | ||
- so that locally committed merge commits will not be flattened | ||
- by running 'git pull'. | ||
+When preserve, also pass `--preserve-merges` along to 'git rebase' | ||
+so that locally committed merge commits will not be flattened | ||
+by running 'git pull'. | ||
+ | ||
*NOTE*: this is a possibly dangerous operation; do *not* use | ||
it unless you understand the implications (see linkgit:git-rebase[1] | ||
@@ -1242,6 +1250,25 @@ filter.<driver>.smudge:: | ||
object to a worktree file upon checkout. See | ||
linkgit:gitattributes[5] for details. | ||
+fsck.<msg-id>:: | ||
+ Allows overriding the message type (error, warn or ignore) of a | ||
+ specific message ID such as `missingEmail`. | ||
++ | ||
+For convenience, fsck prefixes the error/warning with the message ID, | ||
+e.g. "missingEmail: invalid author/committer line - missing email" means | ||
+that setting `fsck.missingEmail = ignore` will hide that issue. | ||
++ | ||
+This feature is intended to support working with legacy repositories | ||
+which cannot be repaired without disruptive changes. | ||
+ | ||
+fsck.skipList:: | ||
+ The path to a sorted list of object names (i.e. one SHA-1 per | ||
+ line) that are known to be broken in a non-fatal way and should | ||
+ be ignored. This feature is useful when an established project | ||
+ should be accepted despite early commits containing errors that | ||
+ can be safely ignored such as invalid committer email addresses. | ||
+ Note: corrupt objects cannot be skipped with this setting. | ||
+ | ||
gc.aggressiveDepth:: | ||
The depth parameter used in the delta compression | ||
algorithm used by 'git gc --aggressive'. This defaults | ||
@@ -1280,28 +1307,34 @@ gc.packRefs:: | ||
gc.pruneExpire:: | ||
When 'git gc' is run, it will call 'prune --expire 2.weeks.ago'. | ||
Override the grace period with this config variable. The value | ||
- "now" may be used to disable this grace period and always prune | ||
- unreachable objects immediately. | ||
- | ||
-gc.pruneWorktreesExpire:: | ||
- When 'git gc' is run, it will call | ||
- 'prune --worktrees --expire 3.months.ago'. | ||
- Override the grace period with this config variable. The value | ||
- "now" may be used to disable the grace period and prune | ||
- $GIT_DIR/worktrees immediately. | ||
+ "now" may be used to disable this grace period and always prune | ||
+ unreachable objects immediately, or "never" may be used to | ||
+ suppress pruning. | ||
+ | ||
+gc.worktreePruneExpire:: | ||
+ When 'git gc' is run, it calls | ||
+ 'git worktree prune --expire 3.months.ago'. | ||
+ This config variable can be used to set a different grace | ||
+ period. The value "now" may be used to disable the grace | ||
+ period and prune $GIT_DIR/worktrees immediately, or "never" | ||
+ may be used to suppress pruning. | ||
gc.reflogExpire:: | ||
gc.<pattern>.reflogExpire:: | ||
'git reflog expire' removes reflog entries older than | ||
- this time; defaults to 90 days. With "<pattern>" (e.g. | ||
+ this time; defaults to 90 days. The value "now" expires all | ||
+ entries immediately, and "never" suppresses expiration | ||
+ altogether. With "<pattern>" (e.g. | ||
"refs/stash") in the middle the setting applies only to | ||
the refs that match the <pattern>. | ||
gc.reflogExpireUnreachable:: | ||
-gc.<ref>.reflogExpireUnreachable:: | ||
+gc.<pattern>.reflogExpireUnreachable:: | ||
'git reflog expire' removes reflog entries older than | ||
this time and are not reachable from the current tip; | ||
- defaults to 30 days. With "<pattern>" (e.g. "refs/stash") | ||
+ defaults to 30 days. The value "now" expires all entries | ||
+ immediately, and "never" suppresses expiration altogether. | ||
+ With "<pattern>" (e.g. "refs/stash") | ||
in the middle, the setting applies only to the refs that | ||
match the <pattern>. | ||
@@ -1576,6 +1609,29 @@ http.saveCookies:: | ||
If set, store cookies received during requests to the file specified by | ||
http.cookieFile. Has no effect if http.cookieFile is unset. | ||
+http.sslVersion:: | ||
+ The SSL version to use when negotiating an SSL connection, if you | ||
+ want to force the default. The available and default version | ||
+ depend on whether libcurl was built against NSS or OpenSSL and the | ||
+ particular configuration of the crypto library in use. Internally | ||
+ this sets the 'CURLOPT_SSL_VERSION' option; see the libcurl | ||
+ documentation for more details on the format of this option and | ||
+ for the ssl version supported. Actually the possible values of | ||
+ this option are: | ||
+ | ||
+ - sslv2 | ||
+ - sslv3 | ||
+ - tlsv1 | ||
+ - tlsv1.0 | ||
+ - tlsv1.1 | ||
+ - tlsv1.2 | ||
+ | ||
++ | ||
+Can be overridden by the 'GIT_SSL_VERSION' environment variable. | ||
+To force git to use libcurl's default ssl version and ignore any | ||
+explicit http.sslversion option, set 'GIT_SSL_VERSION' to the | ||
+empty string. | ||
+ | ||
http.sslCipherList:: | ||
A list of SSL ciphers to use when negotiating an SSL connection. | ||
The available ciphers depend on whether libcurl was built against | ||
@@ -1886,6 +1942,18 @@ mergetool.writeToTemp:: | ||
mergetool.prompt:: | ||
Prompt before each invocation of the merge resolution program. | ||
+notes.mergeStrategy:: | ||
+ Which merge strategy to choose by default when resolving notes | ||
+ conflicts. Must be one of `manual`, `ours`, `theirs`, `union`, or | ||
+ `cat_sort_uniq`. Defaults to `manual`. See "NOTES MERGE STRATEGIES" | ||
+ section of linkgit:git-notes[1] for more information on each strategy. | ||
+ | ||
+notes.<name>.mergeStrategy:: | ||
+ Which merge strategy to choose when doing a notes merge into | ||
+ refs/notes/<name>. This overrides the more general | ||
+ "notes.mergeStrategy". See the "NOTES MERGE STRATEGIES" section in | ||
+ linkgit:git-notes[1] for more information on the available strategies. | ||
+ | ||
notes.displayRef:: | ||
The (fully qualified) refname from which to show notes when | ||
showing commit messages. The value of this variable can be set | ||
@@ -1914,8 +1982,8 @@ notes.rewriteMode:: | ||
When copying notes during a rewrite (see the | ||
"notes.rewrite.<command>" option), determines what to do if | ||
the target commit already has a note. Must be one of | ||
- `overwrite`, `concatenate`, or `ignore`. Defaults to | ||
- `concatenate`. | ||
+ `overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`. | ||
+ Defaults to `concatenate`. | ||
+ | ||
This setting can be overridden with the `GIT_NOTES_REWRITE_MODE` | ||
environment variable. | ||
@@ -2070,9 +2138,9 @@ pull.rebase:: | ||
pull" is run. See "branch.<name>.rebase" for setting this on a | ||
per-branch basis. | ||
+ | ||
- When preserve, also pass `--preserve-merges` along to 'git rebase' | ||
- so that locally committed merge commits will not be flattened | ||
- by running 'git pull'. | ||
+When preserve, also pass `--preserve-merges` along to 'git rebase' | ||
+so that locally committed merge commits will not be flattened | ||
+by running 'git pull'. | ||
+ | ||
*NOTE*: this is a possibly dangerous operation; do *not* use | ||
it unless you understand the implications (see linkgit:git-rebase[1] | ||
@@ -2145,6 +2213,14 @@ push.followTags:: | ||
may override this configuration at time of push by specifying | ||
'--no-follow-tags'. | ||
+push.gpgSign:: | ||
+ May be set to a boolean value, or the string 'if-asked'. A true | ||
+ value causes all pushes to be GPG signed, as if '--signed' is | ||
+ passed to linkgit:git-push[1]. The string 'if-asked' causes | ||
+ pushes to be signed if the server supports it, as if | ||
+ '--signed=if-asked' is passed to 'git push'. A false value may | ||
+ override a value from a lower-priority config file. An explicit | ||
+ command-line flag always overrides this config option. | ||
rebase.stat:: | ||
Whether to show a diffstat of what changed upstream since the last | ||
@@ -2161,6 +2237,22 @@ rebase.autoStash:: | ||
successful rebase might result in non-trivial conflicts. | ||
Defaults to false. | ||
+rebase.missingCommitsCheck:: | ||
+ If set to "warn", git rebase -i will print a warning if some | ||
+ commits are removed (e.g. a line was deleted), however the | ||
+ rebase will still proceed. If set to "error", it will print | ||
+ the previous warning and stop the rebase, 'git rebase | ||
+ --edit-todo' can then be used to correct the error. If set to | ||
+ "ignore", no checking is done. | ||
+ To drop a commit without warning or error, use the `drop` | ||
+ command in the todo-list. | ||
+ Defaults to "ignore". | ||
+ | ||
+rebase.instructionFormat | ||
+ A format string, as specified in linkgit:git-log[1], to be used for | ||
+ the instruction list during an interactive rebase. The format will automatically | ||
+ have the long commit hash prepended to the format. | ||
+ | ||
receive.advertiseAtomic:: | ||
By default, git-receive-pack will advertise the atomic push | ||
capability to its clients. If you don't want to this capability | ||
@@ -2197,6 +2289,28 @@ receive.fsckObjects:: | ||
Defaults to false. If not set, the value of `transfer.fsckObjects` | ||
is used instead. | ||
+receive.fsck.<msg-id>:: | ||
+ When `receive.fsckObjects` is set to true, errors can be switched | ||
+ to warnings and vice versa by configuring the `receive.fsck.<msg-id>` | ||
+ setting where the `<msg-id>` is the fsck message ID and the value | ||
+ is one of `error`, `warn` or `ignore`. For convenience, fsck prefixes | ||
+ the error/warning with the message ID, e.g. "missingEmail: invalid | ||
+ author/committer line - missing email" means that setting | ||
+ `receive.fsck.missingEmail = ignore` will hide that issue. | ||
++ | ||
+This feature is intended to support working with legacy repositories | ||
+which would not pass pushing when `receive.fsckObjects = true`, allowing | ||
+the host to accept repositories with certain known issues but still catch | ||
+other issues. | ||
+ | ||
+receive.fsck.skipList:: | ||
+ The path to a sorted list of object names (i.e. one SHA-1 per | ||
+ line) that are known to be broken in a non-fatal way and should | ||
+ be ignored. This feature is useful when an established project | ||
+ should be accepted despite early commits containing errors that | ||
+ can be safely ignored such as invalid committer email addresses. | ||
+ Note: corrupt objects cannot be skipped with this setting. | ||
+ | ||
receive.unpackLimit:: | ||
If the number of objects received in a push is below this | ||
limit then the objects will be unpacked into loose object | ||
@@ -2242,13 +2356,10 @@ receive.denyNonFastForwards:: | ||
set when initializing a shared repository. | ||
receive.hideRefs:: | ||
- String(s) `receive-pack` uses to decide which refs to omit | ||
- from its initial advertisement. Use more than one | ||
- definitions to specify multiple prefix strings. A ref that | ||
- are under the hierarchies listed on the value of this | ||
- variable is excluded, and is hidden when responding to `git | ||
- push`, and an attempt to update or delete a hidden ref by | ||
- `git push` is rejected. | ||
+ This variable is the same as `transfer.hideRefs`, but applies | ||
+ only to `receive-pack` (and so affects pushes, but not fetches). | ||
+ An attempt to update or delete a hidden ref by `git push` is | ||
+ rejected. | ||
receive.updateServerInfo:: | ||
If set to true, git-receive-pack will run git-update-server-info | ||
@@ -2536,9 +2647,18 @@ transfer.fsckObjects:: | ||
Defaults to false. | ||
transfer.hideRefs:: | ||
- This variable can be used to set both `receive.hideRefs` | ||
- and `uploadpack.hideRefs` at the same time to the same | ||
- values. See entries for these other variables. | ||
+ String(s) `receive-pack` and `upload-pack` use to decide which | ||
+ refs to omit from their initial advertisements. Use more than | ||
+ one definition to specify multiple prefix strings. A ref that is | ||
+ under the hierarchies listed in the value of this variable is | ||
+ excluded, and is hidden when responding to `git push` or `git | ||
+ fetch`. See `receive.hideRefs` and `uploadpack.hideRefs` for | ||
+ program-specific versions of this config. | ||
++ | ||
+You may also include a `!` in front of the ref name to negate the entry, | ||
+explicitly exposing it, even if an earlier entry marked it as hidden. | ||
+If you have multiple hideRefs values, later entries override earlier ones | ||
+(and entries in more-specific config files override less-specific ones). | ||
transfer.unpackLimit:: | ||
When `fetch.unpackLimit` or `receive.unpackLimit` are | ||
@@ -2553,13 +2673,10 @@ uploadarchive.allowUnreachable:: | ||
`false`. | ||
uploadpack.hideRefs:: | ||
- String(s) `upload-pack` uses to decide which refs to omit | ||
- from its initial advertisement. Use more than one | ||
- definitions to specify multiple prefix strings. A ref that | ||
- are under the hierarchies listed on the value of this | ||
- variable is excluded, and is hidden from `git ls-remote`, | ||
- `git fetch`, etc. An attempt to fetch a hidden ref by `git | ||
- fetch` will fail. See also `uploadpack.allowTipSHA1InWant`. | ||
+ This variable is the same as `transfer.hideRefs`, but applies | ||
+ only to `upload-pack` (and so affects only fetches, not pushes). | ||
+ An attempt to fetch a hidden ref by `git fetch` will fail. See | ||
+ also `uploadpack.allowTipSHA1InWant`. | ||
uploadpack.allowTipSHA1InWant:: | ||
When `uploadpack.hideRefs` is in effect, allow `upload-pack` | ||
View
7
Documentation/git-am.txt
@@ -10,7 +10,7 @@ SYNOPSIS | ||
-------- | ||
[verse] | ||
'git am' [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8] | ||
- [--3way] [--interactive] [--committer-date-is-author-date] | ||
+ [--[no-]3way] [--interactive] [--committer-date-is-author-date] | ||
[--ignore-date] [--ignore-space-change | --ignore-whitespace] | ||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>] | ||
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet] | ||
@@ -90,10 +90,13 @@ default. You can use `--no-utf8` to override this. | ||
-3:: | ||
--3way:: | ||
+--no-3way:: | ||
When the patch does not apply cleanly, fall back on | ||
3-way merge if the patch records the identity of blobs | ||
it is supposed to apply to and we have those blobs | ||
- available locally. | ||
+ available locally. `--no-3way` can be used to override | ||
+ am.threeWay configuration variable. For more information, | ||
+ see am.threeWay in linkgit:git-config[1]. | ||
--ignore-space-change:: | ||
--ignore-whitespace:: | ||
View
133
Documentation/git-bisect.txt
@@ -3,7 +3,7 @@ git-bisect(1) | ||
NAME | ||
---- | ||
-git-bisect - Find by binary search the change that introduced a bug | ||
+git-bisect - Use binary search to find the commit that introduced a bug | ||
SYNOPSIS | ||
@@ -16,7 +16,6 @@ DESCRIPTION | ||
The command takes various subcommands, and different options depending | ||
on the subcommand: | ||
- git bisect help | ||
git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...] | ||
git bisect bad [<rev>] | ||
git bisect good [<rev>...] | ||
@@ -26,64 +25,71 @@ on the subcommand: | ||
git bisect replay <logfile> | ||
git bisect log | ||
git bisect run <cmd>... | ||
+ git bisect help | ||
-This command uses 'git rev-list --bisect' to help drive the | ||
-binary search process to find which change introduced a bug, given an | ||
-old "good" commit object name and a later "bad" commit object name. | ||
- | ||
-Getting help | ||
-~~~~~~~~~~~~ | ||
- | ||
-Use "git bisect" to get a short usage description, and "git bisect | ||
-help" or "git bisect -h" to get a long usage description. | ||
+This command uses a binary search algorithm to find which commit in | ||
+your project's history introduced a bug. You use it by first telling | ||
+it a "bad" commit that is known to contain the bug, and a "good" | ||
+commit that is known to be before the bug was introduced. Then `git | ||
+bisect` picks a commit between those two endpoints and asks you | ||
+whether the selected commit is "good" or "bad". It continues narrowing | ||
+down the range until it finds the exact commit that introduced the | ||
+change. | ||
Basic bisect commands: start, bad, good | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
-Using the Linux kernel tree as an example, basic use of the bisect | ||
-command is as follows: | ||
+As an example, suppose you are trying to find the commit that broke a | ||
+feature that was known to work in version `v2.6.13-rc2` of your | ||
+project. You start a bisect session as follows: | ||
------------------------------------------------ | ||
$ git bisect start | ||
$ git bisect bad # Current version is bad | ||
-$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version | ||
- # tested that was good | ||
+$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 is known to be good | ||
------------------------------------------------ | ||
-When you have specified at least one bad and one good version, the | ||
-command bisects the revision tree and outputs something similar to | ||
-the following: | ||
+Once you have specified at least one bad and one good commit, `git | ||
+bisect` selects a commit in the middle of that range of history, | ||
+checks it out, and outputs something similar to the following: | ||
------------------------------------------------ | ||
-Bisecting: 675 revisions left to test after this | ||
+Bisecting: 675 revisions left to test after this (roughly 10 steps) | ||
------------------------------------------------ | ||
-The state in the middle of the set of revisions is then checked out. | ||
-You would now compile that kernel and boot it. If the booted kernel | ||
-works correctly, you would then issue the following command: | ||
+You should now compile the checked-out version and test it. If that | ||
+version works correctly, type | ||
------------------------------------------------ | ||
-$ git bisect good # this one is good | ||
+$ git bisect good | ||
------------------------------------------------ | ||
-The output of this command would be something similar to the following: | ||
+If that version is broken, type | ||
------------------------------------------------ | ||
-Bisecting: 337 revisions left to test after this | ||
+$ git bisect bad | ||
------------------------------------------------ | ||
-You keep repeating this process, compiling the tree, testing it, and | ||
-depending on whether it is good or bad issuing the command "git bisect good" | ||
-or "git bisect bad" to ask for the next bisection. | ||
+Then `git bisect` will respond with something like | ||
+ | ||
+------------------------------------------------ | ||
+Bisecting: 337 revisions left to test after this (roughly 9 steps) | ||
+------------------------------------------------ | ||
+ | ||
+Keep repeating the process: compile the tree, test it, and depending | ||
+on whether it is good or bad run `git bisect good` or `git bisect bad` | ||
+to ask for the next commit that needs testing. | ||
+ | ||
+Eventually there will be no more revisions left to inspect, and the | ||
+command will print out a description of the first bad commit. The | ||
+reference `refs/bisect/bad` will be left pointing at that commit. | ||
-Eventually there will be no more revisions left to bisect, and you | ||
-will have been left with the first bad kernel revision in "refs/bisect/bad". | ||
Bisect reset | ||
~~~~~~~~~~~~ | ||
After a bisect session, to clean up the bisection state and return to | ||
-the original HEAD (i.e., to quit bisecting), issue the following command: | ||
+the original HEAD, issue the following command: | ||
------------------------------------------------ | ||
$ git bisect reset | ||
@@ -100,9 +106,10 @@ instead: | ||
$ git bisect reset <commit> | ||
------------------------------------------------ | ||
-For example, `git bisect reset HEAD` will leave you on the current | ||
-bisection commit and avoid switching commits at all, while `git bisect | ||
-reset bisect/bad` will check out the first bad revision. | ||
+For example, `git bisect reset bisect/bad` will check out the first | ||
+bad revision, while `git bisect reset HEAD` will leave you on the | ||
+current bisection commit and avoid switching commits at all. | ||
+ | ||
Bisect visualize | ||
~~~~~~~~~~~~~~~~ | ||
@@ -147,17 +154,17 @@ $ git bisect replay that-file | ||
Avoiding testing a commit | ||
~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
-If, in the middle of a bisect session, you know that the next suggested | ||
-revision is not a good one to test (e.g. the change the commit | ||
-introduces is known not to work in your environment and you know it | ||
-does not have anything to do with the bug you are chasing), you may | ||
-want to find a nearby commit and try that instead. | ||
+If, in the middle of a bisect session, you know that the suggested | ||
+revision is not a good one to test (e.g. it fails to build and you | ||
+know that the failure does not have anything to do with the bug you | ||
+are chasing), you can manually select a nearby commit and test that | ||
+one instead. | ||
For example: | ||
------------ | ||
$ git bisect good/bad # previous round was good or bad. | ||
-Bisecting: 337 revisions left to test after this | ||
+Bisecting: 337 revisions left to test after this (roughly 9 steps) | ||
$ git bisect visualize # oops, that is uninteresting. | ||
$ git reset --hard HEAD~3 # try 3 revisions before what | ||
# was suggested | ||
@@ -169,18 +176,19 @@ the revision as good or bad in the usual manner. | ||
Bisect skip | ||
~~~~~~~~~~~~ | ||
-Instead of choosing by yourself a nearby commit, you can ask Git | ||
-to do it for you by issuing the command: | ||
+Instead of choosing a nearby commit by yourself, you can ask Git to do | ||
+it for you by issuing the command: | ||
------------ | ||
$ git bisect skip # Current version cannot be tested | ||
------------ | ||
-But Git may eventually be unable to tell the first bad commit among | ||
-a bad commit and one or more skipped commits. | ||
+However, if you skip a commit adjacent to the one you are looking for, | ||
+Git will be unable to tell exactly which of those commits was the | ||
+first bad one. | ||
-You can even skip a range of commits, instead of just one commit, | ||
-using the "'<commit1>'..'<commit2>'" notation. For example: | ||
+You can also skip a range of commits, instead of just one commit, | ||
+using range notation. For example: | ||
------------ | ||
$ git bisect skip v2.5..v2.6 | ||
@@ -196,8 +204,8 @@ would issue the command: | ||
$ git bisect skip v2.5 v2.5..v2.6 | ||
------------ | ||
-This tells the bisect process that the commits between `v2.5` included | ||
-and `v2.6` included should be skipped. | ||
+This tells the bisect process that the commits between `v2.5` and | ||
+`v2.6` (inclusive) should be skipped. | ||
Cutting down bisection by giving more parameters to bisect start | ||
@@ -231,14 +239,14 @@ or bad, you can bisect by issuing the command: | ||
$ git bisect run my_script arguments | ||
------------ | ||
-Note that the script (`my_script` in the above example) should | ||
-exit with code 0 if the current source code is good, and exit with a | ||
-code between 1 and 127 (inclusive), except 125, if the current | ||
-source code is bad. | ||
+Note that the script (`my_script` in the above example) should exit | ||
+with code 0 if the current source code is good/old, and exit with a | ||
+code between 1 and 127 (inclusive), except 125, if the current source | ||
+code is bad/new. | ||
Any other exit code will abort the bisect process. It should be noted | ||
-that a program that terminates via "exit(-1)" leaves $? = 255, (see the | ||
-exit(3) manual page), as the value is chopped with "& 0377". | ||
+that a program that terminates via `exit(-1)` leaves $? = 255, (see the | ||
+exit(3) manual page), as the value is chopped with `& 0377`. | ||
The special exit code 125 should be used when the current source code | ||
cannot be tested. If the script exits with this code, the current | ||
@@ -247,7 +255,7 @@ as the highest sensible value to use for this purpose, because 126 and 127 | ||
are used by POSIX shells to signal specific error status (127 is for | ||
command not found, 126 is for command found but not executable---these | ||
details do not matter, as they are normal errors in the script, as far as | ||
-"bisect run" is concerned). | ||
+`bisect run` is concerned). | ||
You may often find that during a bisect session you want to have | ||
temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a | ||
@@ -260,7 +268,7 @@ next revision to test, the script can apply the patch | ||
before compiling, run the real test, and afterwards decide if the | ||
revision (possibly with the needed patch) passed the test and then | ||
rewind the tree to the pristine state. Finally the script should exit | ||
-with the status of the real test to let the "git bisect run" command loop | ||
+with the status of the real test to let the `git bisect run` command loop | ||
determine the eventual outcome of the bisect session. | ||
OPTIONS | ||
@@ -307,12 +315,12 @@ $ git bisect run ~/test.sh | ||
$ git bisect reset # quit the bisect session | ||
------------ | ||
+ | ||
-Here we use a "test.sh" custom script. In this script, if "make" | ||
+Here we use a `test.sh` custom script. In this script, if `make` | ||
fails, we skip the current commit. | ||
-"check_test_case.sh" should "exit 0" if the test case passes, | ||
-and "exit 1" otherwise. | ||
+`check_test_case.sh` should `exit 0` if the test case passes, | ||
+and `exit 1` otherwise. | ||
+ | ||
-It is safer if both "test.sh" and "check_test_case.sh" are | ||
+It is safer if both `test.sh` and `check_test_case.sh` are | ||
outside the repository to prevent interactions between the bisect, | ||
make and test processes and the scripts. | ||
@@ -379,6 +387,11 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit | ||
has at least one parent whose reachable graph is fully traversable in the sense | ||
required by 'git pack objects'. | ||
+Getting help | ||
+~~~~~~~~~~~~ | ||
+ | ||
+Use `git bisect` to get a short usage description, and `git bisect | ||
+help` or `git bisect -h` to get a long usage description. | ||
SEE ALSO | ||
-------- | ||
View
4
Documentation/git-branch.txt
@@ -197,7 +197,9 @@ start-point is either a local or remote-tracking branch. | ||
--edit-description:: | ||
Open an editor and edit the text to explain what the branch is | ||
- for, to be used by various other commands (e.g. `request-pull`). | ||
+ for, to be used by various other commands (e.g. `format-patch`, | ||
+ `request-pull`, and `merge` (if enabled)). Multi-line explanations | ||
+ may be used. | ||
--contains [<commit>]:: | ||
Only list branches which contain the specified commit (HEAD | ||
View
14
Documentation/git-cat-file.txt
@@ -69,6 +69,20 @@ OPTIONS | ||
not be combined with any other options or arguments. See the | ||
section `BATCH OUTPUT` below for details. | ||
+--batch-all-objects:: | ||
+ Instead of reading a list of objects on stdin, perform the | ||
+ requested batch operation on all objects in the repository and | ||
+ any alternate object stores (not just reachable objects). | ||
+ Requires `--batch` or `--batch-check` be specified. Note that | ||
+ the objects are visited in order sorted by their hashes. | ||
+ | ||
+--buffer:: | ||
+ Normally batch output is flushed after each object is output, so | ||
+ that a process can interactively read and write from | ||
+ `cat-file`. With this option, the output uses normal stdio | ||
+ buffering; this is much more efficient when invoking | ||
+ `--batch-check` on a large number of objects. | ||
+ | ||
--allow-unknown-type:: | ||
Allow -s or -t to query broken/corrupt objects of unknown type. | ||
View
4
Documentation/git-check-ref-format.txt
@@ -94,8 +94,8 @@ OPTIONS | ||
Interpret <refname> as a reference name pattern for a refspec | ||
(as used with remote repositories). If this option is | ||
enabled, <refname> is allowed to contain a single `*` | ||
- in place of a one full pathname component (e.g., | ||
- `foo/*/bar` but not `foo/bar*`). | ||
+ in the refspec (e.g., `foo/bar*/baz` or `foo/bar*baz/` | ||
+ but not `foo/bar*/baz*`). | ||
--normalize:: | ||
Normalize 'refname' by removing any leading slash (`/`) | ||
View
15
Documentation/git-checkout.txt
@@ -120,6 +120,21 @@ entries; instead, unmerged entries are ignored. | ||
--theirs:: | ||
When checking out paths from the index, check out stage #2 | ||
('ours') or #3 ('theirs') for unmerged paths. | ||
++ | ||
+Note that during `git rebase` and `git pull --rebase`, 'ours' and | ||
+'theirs' may appear swapped; `--ours` gives the version from the | ||
+branch the changes are rebased onto, while `--theirs` gives the | ||
+version from the branch that holds your work that is being rebased. | ||
++ | ||
+This is because `rebase` is used in a workflow that treats the | ||
+history at the remote as the shared canonical one, and treats the | ||
+work done on the branch you are rebasing as the third-party work to | ||
+be integrated, and you are temporarily assuming the role of the | ||
+keeper of the canonical history during the rebase. As the keeper of | ||
+the canonical history, you need to view the history from the remote | ||
+as `ours` (i.e. "our shared canonical history"), while what you did | ||
+on your side branch as `theirs` (i.e. "one contributor's work on top | ||
+of it"). | ||
-b <new_branch>:: | ||
Create a new branch named <new_branch> and start it at | ||
View
10
Documentation/git-config.txt
@@ -14,13 +14,13 @@ SYNOPSIS | ||
'git config' [<file-option>] [type] --replace-all name value [value_regex] | ||
'git config' [<file-option>] [type] [-z|--null] --get name [value_regex] | ||
'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex] | ||
-'git config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex] | ||
+'git config' [<file-option>] [type] [-z|--null] [--name-only] --get-regexp name_regex [value_regex] | ||
'git config' [<file-option>] [type] [-z|--null] --get-urlmatch name URL | ||
'git config' [<file-option>] --unset name [value_regex] | ||
'git config' [<file-option>] --unset-all name [value_regex] | ||
'git config' [<file-option>] --rename-section old_name new_name | ||
'git config' [<file-option>] --remove-section name | ||
-'git config' [<file-option>] [-z|--null] -l | --list | ||
+'git config' [<file-option>] [-z|--null] [--name-only] -l | --list | ||
'git config' [<file-option>] --get-color name [default] | ||
'git config' [<file-option>] --get-colorbool name [stdout-is-tty] | ||
'git config' [<file-option>] -e | --edit | ||
@@ -159,7 +159,7 @@ See also <<FILES>>. | ||
-l:: | ||
--list:: | ||
- List all variables set in config file. | ||
+ List all variables set in config file, along with their values. | ||
--bool:: | ||
'git config' will ensure that the output is "true" or "false" | ||
@@ -190,6 +190,10 @@ See also <<FILES>>. | ||
output without getting confused e.g. by values that | ||
contain line breaks. | ||
+--name-only:: | ||
+ Output only the names of config variables for `--list` or | ||
+ `--get-regexp`. | ||
+ | ||
--get-colorbool name [stdout-is-tty]:: | ||
Find the color setting for `name` (e.g. `color.diff`) and output | ||
View
4
Documentation/git-describe.txt
@@ -9,7 +9,7 @@ git-describe - Describe a commit using the most recent tag reachable from it | ||
SYNOPSIS | ||
-------- | ||
[verse] | ||
-'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] <commit-ish>... | ||
+'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...] | ||
'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>] | ||
DESCRIPTION | ||
@@ -27,7 +27,7 @@ see the -a and -s options to linkgit:git-tag[1]. | ||
OPTIONS | ||
------- | ||
<commit-ish>...:: | ||
- Commit-ish object names to describe. | ||
+ Commit-ish object names to describe. Defaults to HEAD if omitted. | ||
--dirty[=<mark>]:: | ||
Describe the working tree. | ||
View
39
Documentation/git-fast-import.txt
@@ -54,7 +54,7 @@ Options for Frontends | ||
~~~~~~~~~~~~~~~~~~~~~ | ||
--cat-blob-fd=<fd>:: | ||
- Write responses to `cat-blob` and `ls` queries to the | ||
+ Write responses to `get-mark`, `cat-blob`, and `ls` queries to the | ||
file descriptor <fd> instead of `stdout`. Allows `progress` | ||
output intended for the end-user to be separated from other | ||
output. | ||
@@ -350,6 +350,11 @@ and control the current import process. More detailed discussion | ||
unless the `done` feature was requested using the | ||
`--done` command-line option or `feature done` command. | ||
+`get-mark`:: | ||
+ Causes fast-import to print the SHA-1 corresponding to a mark | ||
+ to the file descriptor set with `--cat-blob-fd`, or `stdout` if | ||
+ unspecified. | ||
+ | ||
`cat-blob`:: | ||
Causes fast-import to print a blob in 'cat-file --batch' | ||
format to the file descriptor set with `--cat-blob-fd` or | ||
@@ -930,6 +935,25 @@ Placing a `progress` command immediately after a `checkpoint` will | ||
inform the reader when the `checkpoint` has been completed and it | ||
can safely access the refs that fast-import updated. | ||
+`get-mark` | ||
+~~~~~~~~~~ | ||
+Causes fast-import to print the SHA-1 corresponding to a mark to | ||
+stdout or to the file descriptor previously arranged with the | ||
+`--cat-blob-fd` argument. The command otherwise has no impact on the | ||
+current import; its purpose is to retrieve SHA-1s that later commits | ||
+might want to refer to in their commit messages. | ||
+ | ||
+.... | ||
+ 'get-mark' SP ':' <idnum> LF | ||
+.... | ||
+ | ||
+This command can be used anywhere in the stream that comments are | ||
+accepted. In particular, the `get-mark` command can be used in the | ||
+middle of a commit but not in the middle of a `data` command. | ||
+ | ||
+See ``Responses To Commands'' below for details about how to read | ||
+this output safely. | ||
+ | ||
`cat-blob` | ||
~~~~~~~~~~ | ||
Causes fast-import to print a blob to a file descriptor previously | ||
@@ -1000,7 +1024,8 @@ Output uses the same format as `git ls-tree <tree> -- <path>`: | ||
==== | ||
The <dataref> represents the blob, tree, or commit object at <path> | ||
-and can be used in later 'cat-blob', 'filemodify', or 'ls' commands. | ||
+and can be used in later 'get-mark', 'cat-blob', 'filemodify', or | ||
+'ls' commands. | ||
If there is no file or subtree at that path, 'git fast-import' will | ||
instead report | ||
@@ -1042,9 +1067,11 @@ import-marks-if-exists:: | ||
"feature import-marks-if-exists" like a corresponding | ||
command-line option silently skips a nonexistent file. | ||
+get-mark:: | ||
cat-blob:: | ||
ls:: | ||
- Require that the backend support the 'cat-blob' or 'ls' command. | ||
+ Require that the backend support the 'get-mark', 'cat-blob', | ||
+ or 'ls' command respectively. | ||
Versions of fast-import not supporting the specified command | ||
will exit with a message indicating so. | ||
This lets the import error out early with a clear message, | ||
@@ -1124,11 +1151,11 @@ bidirectional pipes: | ||
git fast-import >fast-import-output | ||
==== | ||
-A frontend set up this way can use `progress`, `ls`, and `cat-blob` | ||
-commands to read information from the import in progress. | ||
+A frontend set up this way can use `progress`, `get-mark`, `ls`, and | ||
+`cat-blob` commands to read information from the import in progress. | ||
To avoid deadlock, such frontends must completely consume any | ||
-pending output from `progress`, `ls`, and `cat-blob` before | ||
+pending output from `progress`, `ls`, `get-mark`, and `cat-blob` before | ||
performing writes to fast-import that might block. | ||
Crash Reports | ||
View
2
Documentation/git-format-patch.txt
@@ -213,7 +213,7 @@ feeding the result to `git send-email`. | ||
--[no-]cover-letter:: | ||
In addition to the patches, generate a cover letter file | ||
- containing the shortlog and the overall diffstat. You can | ||
+ containing the branch description, shortlog and the overall diffstat. You can | ||
fill in a description in the file before sending it out. | ||
--notes[=<ref>]:: | ||
View
7
Documentation/git-fsck.txt
@@ -11,7 +11,7 @@ SYNOPSIS | ||
[verse] | ||
'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs] | ||
[--[no-]full] [--strict] [--verbose] [--lost-found] | ||
- [--[no-]dangling] [--[no-]progress] [<object>*] | ||
+ [--[no-]dangling] [--[no-]progress] [--connectivity-only] [<object>*] | ||
DESCRIPTION | ||
----------- | ||
@@ -60,6 +60,11 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs | ||
object pools. This is now default; you can turn it off | ||
with --no-full. | ||
+--connectivity-only:: | ||
+ Check only the connectivity of tags, commits and tree objects. By | ||
+ avoiding to unpack blobs, this speeds up the operation, at the | ||
+ expense of missing corrupt objects or other problematic issues. | ||
+ | ||
--strict:: | ||
Enable more strict checking, namely to catch a file mode | ||
recorded with g+w bit set, which was created by older | ||
View
6
Documentation/git-log.txt
@@ -184,6 +184,12 @@ log.date:: | ||
`--date` option.) Defaults to "default", which means to write | ||
dates like `Sat May 8 19:35:34 2010 -0500`. | ||
+log.follow:: | ||
+ If a single <path> is given to git log, it will act as | ||
+ if the `--follow` option was also used. This has the same | ||
+ limitations as `--follow`, i.e. it cannot be used to follow | ||
+ multiple files and does not work well on non-linear history. | ||
+ | ||
log.showRoot:: | ||
If `false`, `git log` and related commands will not treat the | ||
initial commit as a big creation event. Any root commits in | ||
View
2
Documentation/git-merge.txt
@@ -78,7 +78,7 @@ will be appended to the specified message. | ||
+ | ||
The 'git fmt-merge-msg' command can be | ||
used to give a good default for automated 'git merge' | ||
-invocations. | ||
+invocations. The automated message can include the branch description. | ||
--[no-]rerere-autoupdate:: | ||
Allow the rerere mechanism to update the index with the | ||
View
25
Documentation/git-notes.txt
@@ -101,7 +101,7 @@ merge:: | ||
any) into the current notes ref (called "local"). | ||
+ | ||
If conflicts arise and a strategy for automatically resolving | ||
-conflicting notes (see the -s/--strategy option) is not given, | ||
+conflicting notes (see the "NOTES MERGE STRATEGIES" section) is not given, | ||
the "manual" resolver is used. This resolver checks out the | ||
conflicting notes in a special worktree (`.git/NOTES_MERGE_WORKTREE`), | ||
and instructs the user to manually resolve the conflicts there. | ||
@@ -183,6 +183,7 @@ OPTIONS | ||
When merging notes, resolve notes conflicts using the given | ||
strategy. The following strategies are recognized: "manual" | ||
(default), "ours", "theirs", "union" and "cat_sort_uniq". | ||
+ This option overrides the "notes.mergeStrategy" configuration setting. | ||
See the "NOTES MERGE STRATEGIES" section below for more | ||
information on each notes merge strategy. | ||
@@ -247,6 +248,9 @@ When done, the user can either finalize the merge with | ||
'git notes merge --commit', or abort the merge with | ||
'git notes merge --abort'. | ||
+Users may select an automated merge strategy from among the following using | ||
+either -s/--strategy option or configuring notes.mergeStrategy accordingly: | ||
+ | ||
"ours" automatically resolves conflicting notes in favor of the local | ||
version (i.e. the current notes ref). | ||
@@ -310,6 +314,20 @@ core.notesRef:: | ||
This setting can be overridden through the environment and | ||
command line. | ||
+notes.mergeStrategy:: | ||
+ Which merge strategy to choose by default when resolving notes | ||
+ conflicts. Must be one of `manual`, `ours`, `theirs`, `union`, or | ||
+ `cat_sort_uniq`. Defaults to `manual`. See "NOTES MERGE STRATEGIES" | ||
+ section above for more information on each strategy. | ||
++ | ||
+This setting can be overridden by passing the `--strategy` option. | ||
+ | ||
+notes.<name>.mergeStrategy:: | ||
+ Which merge strategy to choose when doing a notes merge into | ||
+ refs/notes/<name>. This overrides the more general | ||
+ "notes.mergeStrategy". See the "NOTES MERGE STRATEGIES" section above | ||
+ for more information on each available strategy. | ||
+ | ||
notes.displayRef:: | ||
Which ref (or refs, if a glob or specified more than once), in | ||
addition to the default set by `core.notesRef` or | ||
@@ -331,7 +349,8 @@ environment variable. | ||
notes.rewriteMode:: | ||
When copying notes during a rewrite, what to do if the target | ||
commit already has a note. Must be one of `overwrite`, | ||
- `concatenate`, and `ignore`. Defaults to `concatenate`. | ||
+ `concatenate`, `cat_sort_uniq`, or `ignore`. Defaults to | ||
+ `concatenate`. | ||
+ | ||
This setting can be overridden with the `GIT_NOTES_REWRITE_MODE` | ||
environment variable. | ||
@@ -368,7 +387,7 @@ does not match any refs is silently ignored. | ||
'GIT_NOTES_REWRITE_MODE':: | ||
When copying notes during a rewrite, what to do if the target | ||
commit already has a note. | ||
- Must be one of `overwrite`, `concatenate`, and `ignore`. | ||
+ Must be one of `overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`. | ||
This overrides the `core.rewriteMode` setting. | ||
'GIT_NOTES_REWRITE_REF':: | ||
View
15
Documentation/git-push.txt
@@ -11,7 +11,8 @@ SYNOPSIS | ||
[verse] | ||
'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>] | ||
[--repo=<repository>] [-f | --force] [--prune] [-v | --verbose] | ||
- [-u | --set-upstream] [--signed] | ||
+ [-u | --set-upstream] | ||
+ [--[no-]signed|--sign=(true|false|if-asked)] | ||
[--force-with-lease[=<refname>[:<expect>]]] | ||
[--no-verify] [<repository> [<refspec>...]] | ||
@@ -132,12 +133,16 @@ already exists on the remote side. | ||
with configuration variable 'push.followTags'. For more | ||
information, see 'push.followTags' in linkgit:git-config[1]. | ||
- | ||
---signed:: | ||
+--[no-]signed:: | ||
+--sign=(true|false|if-asked):: | ||
GPG-sign the push request to update refs on the receiving | ||
side, to allow it to be checked by the hooks and/or be | ||
- logged. See linkgit:git-receive-pack[1] for the details | ||
- on the receiving end. | ||
+ logged. If `false` or `--no-signed`, no signing will be | ||
+ attempted. If `true` or `--signed`, the push will fail if the | ||
+ server does not support signed pushes. If set to `if-asked`, | ||
+ sign if and only if the server supports signed pushes. The push | ||
+ will also fail if the actual call to `gpg --sign` fails. See | ||
+ linkgit:git-receive-pack[1] for the details on the receiving end. | ||
--[no-]atomic:: | ||
Use an atomic transaction on the remote side if available. | ||
View
16
Documentation/git-rebase.txt
@@ -213,6 +213,15 @@ rebase.autoSquash:: | ||
rebase.autoStash:: | ||
If set to true enable '--autostash' option by default. | ||
+rebase.missingCommitsCheck:: | ||
+ If set to "warn", print warnings about removed commits in | ||
+ interactive mode. If set to "error", print the warnings and | ||
+ stop the rebase. If set to "ignore", no checking is | ||
+ done. "ignore" by default. | ||
+ | ||
+rebase.instructionFormat:: | ||
+ Custom commit list format to use during an '--interactive' rebase. | ||
+ | ||
OPTIONS | ||
------- | ||
--onto <newbase>:: | ||
@@ -359,6 +368,10 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`. | ||
Make a list of the commits which are about to be rebased. Let the | ||
user edit that list before rebasing. This mode can also be used to | ||
split commits (see SPLITTING COMMITS below). | ||
++ | ||
+The commit list format can be changed by setting the configuration option | ||
+rebase.instructionFormat. A customized instruction format will automatically | ||
+have the long commit hash prepended to the format. | ||
-p:: | ||
--preserve-merges:: | ||
@@ -514,6 +527,9 @@ rebasing. | ||
If you just want to edit the commit message for a commit, replace the | ||
command "pick" with the command "reword". | ||
+To drop a commit, replace the command "pick" with "drop", or just | ||
+delete the matching line. | ||
+ | ||
If you want to fold two or more commits into one, replace the command | ||
"pick" for the second and subsequent commits with "squash" or "fixup". | ||
If the commits had different authors, the folded commit will be | ||
View
4
Documentation/git-reflog.txt
@@ -23,6 +23,7 @@ depending on the subcommand: | ||
[--dry-run] [--verbose] [--all | <refs>...] | ||
'git reflog delete' [--rewrite] [--updateref] | ||
[--dry-run] [--verbose] ref@\{specifier\}... | ||
+'git reflog exists' <ref> | ||
Reference logs, or "reflogs", record when the tips of branches and | ||
other references were updated in the local repository. Reflogs are | ||
@@ -52,6 +53,9 @@ argument must be an _exact_ entry (e.g. "`git reflog delete | ||
master@{2}`"). This subcommand is also typically not used directly by | ||
end users. | ||
+The "exists" subcommand checks whether a ref has a reflog. It exits | ||
+with zero status if the reflog exists, and non-zero status if it does | ||
+not. | ||
OPTIONS | ||
------- | ||
View
3
Documentation/git-request-pull.txt
@@ -14,7 +14,8 @@ DESCRIPTION | ||
----------- | ||
Generate a request asking your upstream project to pull changes into | ||
-their tree. The request, printed to the standard output, summarizes | ||
+their tree. The request, printed to the standard output, | ||
+begins with the branch description, summarizes | ||
the changes and indicates from where they can be pulled. | ||
The upstream project is expected to have the commit named by | ||
View
4
Documentation/git-rev-parse.txt
@@ -311,8 +311,8 @@ Each line of options has this format: | ||
`<opt-spec>`:: | ||
its format is the short option character, then the long option name | ||
separated by a comma. Both parts are not required, though at least one | ||
- is necessary. `h,help`, `dry-run` and `f` are all three correct | ||
- `<opt-spec>`. | ||
+ is necessary. May not contain any of the `<flags>` characters. | ||
+ `h,help`, `dry-run` and `f` are examples of correct `<opt-spec>`. | ||
`<flags>`:: | ||
`<flags>` are of `*`, `=`, `?` or `!`. | ||
View
25
Documentation/git-send-email.txt
@@ -49,17 +49,17 @@ Composing | ||
of 'sendemail.annotate'. See the CONFIGURATION section for | ||
'sendemail.multiEdit'. | ||
---bcc=<address>:: | ||
+--bcc=<address>,...:: | ||
Specify a "Bcc:" value for each email. Default is the value of | ||
'sendemail.bcc'. | ||
+ | ||
-The --bcc option must be repeated for each user you want on the bcc list. | ||
+This option may be specified multiple times. | ||
---cc=<address>:: | ||
+--cc=<address>,...:: | ||
Specify a starting "Cc:" value for each email. | ||
Default is the value of 'sendemail.cc'. | ||
+ | ||
-The --cc option must be repeated for each user you want on the cc list. | ||
+This option may be specified multiple times. | ||
--compose:: | ||
Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1]) | ||
@@ -110,13 +110,13 @@ is not set, this will be prompted for. | ||
Only necessary if --compose is also set. If --compose | ||
is not set, this will be prompted for. | ||
---to=<address>:: | ||
+--to=<address>,...:: | ||
Specify the primary recipient of the emails generated. Generally, this | ||
will be the upstream maintainer of the project involved. Default is the | ||
value of the 'sendemail.to' configuration value; if that is unspecified, | ||
and --to-cmd is not specified, this will be prompted for. | ||
+ | ||
-The --to option must be repeated for each user you want on the to list. | ||
+This option may be specified multiple times. | ||
--8bit-encoding=<encoding>:: | ||
When encountering a non-ASCII message or subject that does not | ||
@@ -171,6 +171,19 @@ Sending | ||
to determine your FQDN automatically. Default is the value of | ||
'sendemail.smtpDomain'. | ||
+--smtp-auth=<mechanisms>:: | ||
+ Whitespace-separated list of allowed SMTP-AUTH mechanisms. This setting | ||
+ forces using only the listed mechanisms. Example: | ||
++ | ||
+------ | ||
+$ git send-email --smtp-auth="PLAIN LOGIN GSSAPI" ... | ||
+------ | ||
++ | ||
+If at least one of the specified mechanisms matches the ones advertised by the | ||
+SMTP server and if it is supported by the utilized SASL library, the mechanism | ||
+is used for authentication. If neither 'sendemail.smtpAuth' nor '--smtp-auth' | ||
+is specified, all mechanisms supported by the SASL library can be used. | ||
+ | ||
--smtp-pass[=<password>]:: | ||
Password for SMTP-AUTH. The argument is optional: If no | ||
argument is specified, then the empty string is used as | ||
View
16
Documentation/git-send-pack.txt
@@ -9,7 +9,10 @@ git-send-pack - Push objects over Git protocol to another repository | ||
SYNOPSIS | ||
-------- | ||
[verse] | ||
-'git send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [--atomic] [<host>:]<directory> [<ref>...] | ||
+'git send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] | ||
+ [--verbose] [--thin] [--atomic] | ||
+ [--[no-]signed|--sign=(true|false|if-asked)] | ||
+ [<host>:]<directory> [<ref>...] | ||
DESCRIPTION | ||
----------- | ||
@@ -67,6 +70,17 @@ be in a separate packet, and the list must end with a flush packet. | ||
fails to update then the entire push will fail without changing any | ||
refs. | ||
+--[no-]signed:: | ||
+--sign=(true|false|if-asked):: | ||
+ GPG-sign the push request to update refs on the receiving | ||
+ side, to allow it to be checked by the hooks and/or be | ||
+ logged. If `false` or `--no-signed`, no signing will be | ||
+ attempted. If `true` or `--signed`, the push will fail if the | ||
+ server does not support signed pushes. If set to `if-asked`, | ||
+ sign if and only if the server supports signed pushes. The push | ||
+ will also fail if the actual call to `gpg --sign` fails. See | ||
+ linkgit:git-receive-pack[1] for the details on the receiving end. | ||
+ | ||
<host>:: | ||
A remote host to house the repository. When this | ||
part is specified, 'git-receive-pack' is invoked via | ||
View
3
Documentation/git-svn.txt
@@ -174,6 +174,9 @@ Skip "branches" and "tags" of first level directories;; | ||
(including automatic fetches due to 'clone', 'dcommit', | ||
'rebase', etc) on a given repository. '--ignore-paths' takes | ||
precedence over '--include-paths'. | ||
++ | ||
+[verse] | ||
+config key: svn-remote.<name>.include-paths | ||
--log-window-size=<n>;; | ||
Fetch <n> log entries per request when scanning Subversion history. | ||
View
6
Documentation/git-tag.txt
@@ -13,8 +13,7 @@ SYNOPSIS | ||
<tagname> [<commit> | <object>] | ||
'git tag' -d <tagname>... | ||
'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>] | ||
- [--column[=<options>] | --no-column] [<pattern>...] | ||
- [<pattern>...] | ||
+ [--column[=<options>] | --no-column] [--create-reflog] [<pattern>...] | ||
'git tag' -v <tagname>... | ||
DESCRIPTION | ||
@@ -143,6 +142,9 @@ This option is only applicable when listing tags without annotation lines. | ||
all, 'whitespace' removes just leading/trailing whitespace lines and | ||
'strip' removes both whitespace and commentary. | ||
+--create-reflog:: | ||
+ Create a reflog for the tag. | ||
+ | ||
<tagname>:: | ||
The name of the tag to create, delete, or describe. | ||
The new tag name must pass all checks defined by | ||
View
124
Documentation/git-tools.txt
@@ -1,118 +1,10 @@ | ||
-A short Git tools survey | ||
-======================== | ||
+Git Tools | ||
+========= | ||
+When Git was young, people looking for third-party Git-related tools came | ||
+to the Git project itself to find them, thus a list of such tools was | ||
+maintained here. These days, however, search engines fill that role much | ||
+more efficiently, so this manually-maintained list has been retired. | ||
-Introduction | ||
------------- | ||
- | ||
-Apart from Git contrib/ area there are some others third-party tools | ||
-you may want to look. | ||
- | ||
-This document presents a brief summary of each tool and the corresponding | ||
-link. | ||
- | ||
- | ||
-Alternative/Augmentative Porcelains | ||
------------------------------------ | ||
- | ||
- - *Cogito* (http://www.kernel.org/pub/software/scm/cogito/) | ||
- | ||
- Cogito is a version control system layered on top of the Git tree history | ||
- storage system. It aims at seamless user interface and ease of use, | ||
- providing generally smoother user experience than the "raw" Core Git | ||
- itself and indeed many other version control systems. | ||
- | ||
- Cogito is no longer maintained as most of its functionality | ||
- is now in core Git. | ||
- | ||
- | ||
- - *pg* (http://www.spearce.org/category/projects/scm/pg/) | ||
- | ||
- pg is a shell script wrapper around Git to help the user manage a set of | ||
- patches to files. pg is somewhat like quilt or StGit, but it does have a | ||
- slightly different feature set. | ||
- | ||
- | ||
- - *StGit* (http://www.procode.org/stgit/) | ||
- | ||
- Stacked Git provides a quilt-like patch management functionality in the | ||
- Git environment. You can easily manage your patches in the scope of Git | ||
- until they get merged upstream. | ||
- | ||
- | ||
-History Viewers | ||
---------------- | ||
- | ||
- - *gitk* (shipped with git-core) | ||
- | ||
- gitk is a simple Tk GUI for browsing history of Git repositories easily. | ||
- | ||
- | ||
- - *gitview* (contrib/) | ||
- | ||
- gitview is a GTK based repository browser for Git | ||
- | ||
- | ||
- - *gitweb* (shipped with git-core) | ||
- | ||
- Gitweb provides full-fledged web interface for Git repositories. | ||
- | ||
- | ||
- - *qgit* (http://digilander.libero.it/mcostalba/) | ||
- | ||
- QGit is a git/StGit GUI viewer built on Qt/C++. QGit could be used | ||
- to browse history and directory tree, view annotated files, commit | ||
- changes cherry picking single files or applying patches. | ||
- Currently it is the fastest and most feature rich among the Git | ||
- viewers and commit tools. | ||
- | ||
- - *tig* (http://jonas.nitro.dk/tig/) | ||
- | ||
- tig by Jonas Fonseca is a simple Git repository browser | ||
- written using ncurses. Basically, it just acts as a front-end | ||
- for git-log and git-show/git-diff. Additionally, you can also | ||
- use it as a pager for Git commands. | ||
- | ||
- | ||
-Foreign SCM interface | ||
---------------------- | ||
- | ||
- - *git-svn* (shipped with git-core) | ||
- | ||
- git-svn is a simple conduit for changesets between a single Subversion | ||
- branch and Git. | ||
- | ||
- | ||
- - *quilt2git / git2quilt* (http://home-tj.org/wiki/index.php/Misc) | ||
- | ||
- These utilities convert patch series in a quilt repository and commit | ||
- series in Git back and forth. | ||
- | ||
- | ||
- - *hg-to-git* (contrib/) | ||
- | ||
- hg-to-git converts a Mercurial repository into a Git one, and | ||
- preserves the full branch history in the process. hg-to-git can | ||
- also be used in an incremental way to keep the Git repository | ||
- in sync with the master Mercurial repository. | ||
- | ||
- | ||
-Others | ||
------- | ||
- | ||
- - *(h)gct* (http://www.cyd.liu.se/users/~freku045/gct/) | ||
- | ||
- Commit Tool or (h)gct is a GUI enabled commit tool for Git and | ||
- Mercurial (hg). It allows the user to view diffs, select which files | ||
- to committed (or ignored / reverted) write commit messages and | ||
- perform the commit itself. | ||
- | ||
- - *git.el* (contrib/) | ||
- | ||
- This is an Emacs interface for Git. The user interface is modelled on | ||
- pcl-cvs. It has been developed on Emacs 21 and will probably need some | ||
- tweaking to work on XEmacs. | ||
- | ||
- | ||
-http://git.or.cz/gitwiki/InterfacesFrontendsAndTools has more | ||
-comprehensive list. | ||
+See also the `contrib/` area, and the Git wiki: | ||
+http://git.or.cz/gitwiki/InterfacesFrontendsAndTools |
View
5
Documentation/git-update-ref.txt
@@ -8,7 +8,7 @@ git-update-ref - Update the object name stored in a ref safely | ||
SYNOPSIS | ||
-------- | ||
[verse] | ||
-'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>] | --stdin [-z]) | ||
+'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] [--create-reflog] <ref> <newvalue> [<oldvalue>] | --stdin [-z]) | ||
DESCRIPTION | ||
----------- | ||
@@ -67,6 +67,9 @@ performs all modifications together. Specify commands of the form: | ||
verify SP <ref> [SP <oldvalue>] LF | ||
option SP <opt> LF | ||
+With `--create-reflog`, update-ref will create a reflog for each ref | ||
+even if one would not ordinarily be created. | ||
+ | ||
Quote fields containing whitespace as if they were strings in C source | ||
code; i.e., surrounded by double-quotes and with backslash escapes. | ||
Use 40 "0" characters or the empty string to specify a zero value. To | ||
View
4
Documentation/git-verify-commit.txt
@@ -16,6 +16,10 @@ Validates the gpg signature created by 'git commit -S'. | ||
OPTIONS | ||
------- | ||
+--raw:: | ||
+ Print the raw gpg status output to standard error instead of the normal | ||
+ human-readable output. | ||
+ | ||
-v:: | ||
--verbose:: | ||
Print the contents of the commit object before validating it. | ||
View
4
Documentation/git-verify-tag.txt
@@ -16,6 +16,10 @@ Validates the gpg signature created by 'git tag'. | ||
OPTIONS | ||
------- | ||
+--raw:: | ||
+ Print the raw gpg status output to standard error instead of the normal | ||
+ human-readable output. | ||
+ | ||
-v:: | ||
--verbose:: | ||
Print the contents of the tag object before validating it. | ||
View
48
Documentation/git-worktree.txt
@@ -3,7 +3,7 @@ git-worktree(1) | ||
NAME | ||
---- | ||
-git-worktree - Manage multiple worktrees | ||
+git-worktree - Manage multiple working trees | ||
SYNOPSIS | ||
@@ -15,7 +15,7 @@ SYNOPSIS | ||
DESCRIPTION | ||
----------- | ||
-Manage multiple worktrees attached to the same repository. | ||
+Manage multiple working trees attached to the same repository. | ||
A git repository can support multiple working trees, allowing you to check | ||
out more than one branch at a time. With `git worktree add` a new working | ||
@@ -27,19 +27,19 @@ bare repository) and zero or more linked working trees. | ||
When you are done with a linked working tree you can simply delete it. | ||
The working tree's administrative files in the repository (see | ||
"DETAILS" below) will eventually be removed automatically (see | ||
-`gc.pruneworktreesexpire` in linkgit::git-config[1]), or you can run | ||
+`gc.worktreePruneExpire` in linkgit:git-config[1]), or you can run | ||
`git worktree prune` in the main or any linked working tree to | ||
clean up any stale administrative files. | ||
-If you move a linked working directory to another file system, or | ||
+If you move a linked working tree to another file system, or | ||
within a file system that does not support hard links, you need to run | ||
-at least one git command inside the linked working directory | ||
+at least one git command inside the linked working tree | ||
(e.g. `git status`) in order to update its administrative files in the | ||
repository so that they do not get automatically pruned. | ||
If a linked working tree is stored on a portable device or network share | ||
which is not always mounted, you can prevent its administrative files from | ||
-being pruned by creating a file named 'lock' alongside the other | ||
+being pruned by creating a file named 'locked' alongside the other | ||
administrative files, optionally containing a plain text reason that | ||
pruning should be suppressed. See section "DETAILS" for more information. | ||
@@ -51,9 +51,9 @@ Create `<path>` and checkout `<branch>` into it. The new working directory | ||
is linked to the current repository, sharing everything except working | ||
directory specific files such as HEAD, index, etc. | ||
+ | ||
-If `<branch>` is omitted and neither `-b` nor `-B` is used, then, as a | ||
-convenience, a new branch based at HEAD is created automatically, as if | ||
-`-b $(basename <path>)` was specified. | ||
+If `<branch>` is omitted and neither `-b` nor `-B` nor `--detached` used, | ||
+then, as a convenience, a new branch based at HEAD is created automatically, | ||
+as if `-b $(basename <path>)` was specified. | ||
prune:: | ||
@@ -64,22 +64,22 @@ OPTIONS | ||
-f:: | ||
--force:: | ||
- By default, `add` refuses to create a new worktree when `<branch>` | ||
- is already checked out by another worktree. This option overrides | ||
+ By default, `add` refuses to create a new working tree when `<branch>` | ||
+ is already checked out by another working tree. This option overrides | ||
that safeguard. | ||
-b <new-branch>:: | ||
-B <new-branch>:: | ||
With `add`, create a new branch named `<new-branch>` starting at | ||
- `<branch>`, and check out `<new-branch>` into the new worktree. | ||
+ `<branch>`, and check out `<new-branch>` into the new working tree. | ||
If `<branch>` is omitted, it defaults to HEAD. | ||
By default, `-b` refuses to create a new branch if it already | ||
exists. `-B` overrides this safeguard, resetting `<new-branch>` to | ||
`<branch>`. | ||
--detach:: | ||
- With `add`, detach HEAD in the new worktree. See "DETACHED HEAD" in | ||
- linkgit:git-checkout[1]. | ||
+ With `add`, detach HEAD in the new working tree. See "DETACHED HEAD" | ||
+ in linkgit:git-checkout[1]. | ||
-n:: | ||
--dry-run:: | ||
@@ -91,7 +91,7 @@ OPTIONS | ||
With `prune`, report all removals. | ||
--expire <time>:: | ||
- With `prune`, only expire unused worktrees older than <time>. | ||
+ With `prune`, only expire unused working trees older than <time>. | ||
DETAILS | ||
------- | ||
@@ -124,7 +124,7 @@ thumb is do not make any assumption about whether a path belongs to | ||
$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something | ||
inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path. | ||
-To prevent a $GIT_DIR/worktrees entry from from being pruned (which | ||
+To prevent a $GIT_DIR/worktrees entry from being pruned (which | ||
can be useful in some situations, such as when the | ||
entry's working tree is stored on a portable device), add a file named | ||
'locked' to the entry's directory. The file contains the reason in | ||
@@ -139,9 +139,9 @@ EXAMPLES | ||
You are in the middle of a refactoring session and your boss comes in and | ||
demands that you fix something immediately. You might typically use | ||
linkgit:git-stash[1] to store your changes away temporarily, however, your | ||
-worktree is in such a state of disarray (with new, moved, and removed files, | ||
-and other bits and pieces strewn around) that you don't want to risk | ||
-disturbing any of it. Instead, you create a temporary linked worktree to | ||
+working tree is in such a state of disarray (with new, moved, and removed | ||
+files, and other bits and pieces strewn around) that you don't want to risk | ||
+disturbing any of it. Instead, you create a temporary linked working tree to | ||
make the emergency fix, remove it when done, and then resume your earlier | ||
refactoring session. | ||
@@ -164,12 +164,12 @@ checkouts of a superproject. | ||
git-worktree could provide more automation for tasks currently | ||
performed manually, such as: | ||
-- `remove` to remove a linked worktree and its administrative files (and | ||
- warn if the worktree is dirty) | ||
-- `mv` to move or rename a worktree and update its administrative files | ||
-- `list` to list linked worktrees | ||
+- `remove` to remove a linked working tree and its administrative files (and | ||
+ warn if the working tree is dirty) | ||
+- `mv` to move or rename a working tree and update its administrative files | ||
+- `list` to list linked working trees | ||
- `lock` to prevent automatic pruning of administrative files (for instance, | ||
- for a worktree on a portable device) | ||
+ for a working tree on a portable device) | ||
GIT | ||
--- | ||
View
37
Documentation/git.txt
@@ -43,14 +43,24 @@ unreleased) version of Git, that is available from the 'master' | ||
branch of the `git.git` repository. | ||
Documentation for older releases are available here: | ||
-* link:v2.5.0/git.html[documentation for release 2.5] | ||
+* link:v2.6.0/git.html[documentation for release 2.6] | ||
* release notes for | ||
- link:RelNotes/2.5.0.txt[2.5], | ||
+ link:RelNotes/2.6.0.txt[2.6]. | ||
-* link:v2.4.7/git.html[documentation for release 2.4.7] | ||
+* link:v2.5.3/git.html[documentation for release 2.5.3] | ||
* release notes for | ||
+ link:RelNotes/2.5.3.txt[2.5.3], | ||
+ link:RelNotes/2.5.2.txt[2.5.2], | ||
+ link:RelNotes/2.5.1.txt[2.5.1], | ||
+ link:RelNotes/2.5.0.txt[2.5]. | ||
+ | ||
+* link:v2.4.9/git.html[documentation for release 2.4.9] | ||
+ | ||
+* release notes for | ||
+ link:RelNotes/2.4.9.txt[2.4.9], | ||
+ link:RelNotes/2.4.8.txt[2.4.8], | ||
link:RelNotes/2.4.7.txt[2.4.7], | ||
link:RelNotes/2.4.6.txt[2.4.6], | ||
link:RelNotes/2.4.5.txt[2.4.5], | ||
@@ -60,9 +70,10 @@ Documentation for older releases are available here: | ||
link:RelNotes/2.4.1.txt[2.4.1], | ||
link:RelNotes/2.4.0.txt[2.4]. | ||
-* link:v2.3.8/git.html[documentation for release 2.3.8] | ||
+* link:v2.3.9/git.html[documentation for release 2.3.9] | ||
* release notes for | ||
+ link:RelNotes/2.3.9.txt[2.3.9], | ||
link:RelNotes/2.3.8.txt[2.3.8], | ||
link:RelNotes/2.3.7.txt[2.3.7], | ||
link:RelNotes/2.3.6.txt[2.3.6], | ||
@@ -73,9 +84,10 @@ Documentation for older releases are available here: | ||
link:RelNotes/2.3.1.txt[2.3.1], | ||
link:RelNotes/2.3.0.txt[2.3]. | ||
-* link:v2.2.2/git.html[documentation for release 2.2.2] | ||
+* link:v2.2.3/git.html[documentation for release 2.2.3] | ||
* release notes for | ||
+ link:RelNotes/2.2.3.txt[2.2.3], | ||
link:RelNotes/2.2.2.txt[2.2.2], | ||
link:RelNotes/2.2.1.txt[2.2.1], | ||
link:RelNotes/2.2.0.txt[2.2]. | ||
@@ -780,7 +792,7 @@ The Git Repository | ||
~~~~~~~~~~~~~~~~~~ | ||
These environment variables apply to 'all' core Git commands. Nb: it | ||
is worth noting that they may be used/overridden by SCMS sitting above | ||
-Git so take care if using Cogito etc. | ||
+Git so take care if using a foreign front-end. | ||
'GIT_INDEX_FILE':: | ||
This environment allows the specification of an alternate | ||
@@ -1009,9 +1021,20 @@ Unsetting the variable, or setting it to empty, "0" or | ||
Enables trace messages for all packets coming in or out of a | ||
given program. This can help with debugging object negotiation | ||
or other protocol issues. Tracing is turned off at a packet | ||
- starting with "PACK". | ||
+ starting with "PACK" (but see 'GIT_TRACE_PACKFILE' below). | ||
See 'GIT_TRACE' for available trace output options. | ||
+'GIT_TRACE_PACKFILE':: | ||
+ Enables tracing of packfiles sent or received by a | ||
+ given program. Unlike other trace output, this trace is | ||
+ verbatim: no headers, and no quoting of binary data. You almost | ||
+ certainly want to direct into a file (e.g., | ||
+ `GIT_TRACE_PACKFILE=/tmp/my.pack`) rather than displaying it on | ||
+ the terminal or mixing it with other trace output. | ||
++ | ||
+Note that this is currently only implemented for the client side | ||
+of clones and fetches. | ||
+ | ||
'GIT_TRACE_PERFORMANCE':: | ||
Enables performance related trace messages, e.g. total execution | ||
time of each Git command. | ||
View
2
Documentation/gitattributes.txt
@@ -527,6 +527,8 @@ patterns are available: | ||
- `fortran` suitable for source code in the Fortran language. | ||
+- `fountain` suitable for Fountain documents. | ||
+ | ||
- `html` suitable for HTML/XHTML documents. | ||
- `java` suitable for source code in the Java language. | ||
View
3
Documentation/gitremote-helpers.txt
@@ -448,6 +448,9 @@ set by Git if the remote helper has the 'option' capability. | ||
'option update-shallow {'true'|'false'}:: | ||
Allow to extend .git/shallow if the new refs require it. | ||
+'option pushcert {'true'|'false'}:: | ||
+ GPG sign pushes. | ||
+ | ||
SEE ALSO | ||
-------- | ||
linkgit:git-remote[1] | ||
View
22
Documentation/gitrepository-layout.txt
@@ -251,25 +251,25 @@ modules:: | ||
Contains the git-repositories of the submodules. | ||
worktrees:: | ||
- Contains worktree specific information of linked | ||
- checkouts. Each subdirectory contains the worktree-related | ||
- part of a linked checkout. This directory is ignored if | ||
- $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/worktrees" will be | ||
- used instead. | ||
+ Contains administrative data for linked | ||
+ working trees. Each subdirectory contains the working tree-related | ||
+ part of a linked working tree. This directory is ignored if | ||
+ $GIT_COMMON_DIR is set, in which case | ||
+ "$GIT_COMMON_DIR/worktrees" will be used instead. | ||
worktrees/<id>/gitdir:: | ||
A text file containing the absolute path back to the .git file | ||
that points to here. This is used to check if the linked | ||
repository has been manually removed and there is no need to | ||
- keep this directory any more. mtime of this file should be | ||
+ keep this directory any more. The mtime of this file should be | ||
updated every time the linked repository is accessed. | ||
worktrees/<id>/locked:: | ||
- If this file exists, the linked repository may be on a | ||
- portable device and not available. It does not mean that the | ||
- linked repository is gone and `worktrees/<id>` could be | ||
- removed. The file's content contains a reason string on why | ||
- the repository is locked. | ||
+ If this file exists, the linked working tree may be on a | ||
+ portable device and not available. The presence of this file | ||
+ prevents `worktrees/<id>` from being pruned either automatically | ||
+ or manually by `git worktree prune`. The file may contain a string | ||
+ explaining why the repository is locked. | ||
worktrees/<id>/link:: | ||
If this file exists, it is a hard link to the linked .git | ||
View
21
Documentation/glossary-content.txt
@@ -411,6 +411,27 @@ exclude;; | ||
core Git. Porcelains expose more of a <<def_SCM,SCM>> | ||
interface than the <<def_plumbing,plumbing>>. | ||
+[[def_per_worktree_ref]]per-worktree ref:: | ||
+ Refs that are per-<<def_working_tree,worktree>>, rather than | ||
+ global. This is presently only <<def_HEAD,HEAD>>, but might | ||
+ later include other unusual refs. | ||
+ | ||
+[[def_pseudoref]]pseudoref:: | ||
+ Pseudorefs are a class of files under `$GIT_DIR` which behave | ||
+ like refs for the purposes of rev-parse, but which are treated | ||
+ specially by git. Pseudorefs both have names that are all-caps, | ||
+ and always start with a line consisting of a | ||
+ <<def_SHA1,SHA-1>> followed by whitespace. So, HEAD is not a | ||
+ pseudoref, because it is sometimes a symbolic ref. They might | ||
+ optionally contain some additional data. `MERGE_HEAD` and | ||
+ `CHERRY_PICK_HEAD` are examples. Unlike | ||
+ <<def_per_worktree_ref,per-worktree refs>>, these files cannot | ||
+ be symbolic refs, and never have reflogs. They also cannot be | ||
+ updated through the normal ref update machinery. Instead, | ||
+ they are updated by directly writing to the files. However, | ||
+ they can be read as if they were refs, so `git rev-parse | ||
+ MERGE_HEAD` will work. | ||
+ | ||
[[def_pull]]pull:: | ||
Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and | ||
<<def_merge,merge>> it. See also linkgit:git-pull[1]. | ||
View
33
Documentation/i18n.txt
@@ -1,18 +1,31 @@ | ||
-At the core level, Git is character encoding agnostic. | ||
- | ||
- - The pathnames recorded in the index and in the tree objects | ||
- are treated as uninterpreted sequences of non-NUL bytes. | ||
- What readdir(2) returns are what are recorded and compared | ||
- with the data Git keeps track of, which in turn are expected | ||
- to be what lstat(2) and creat(2) accepts. There is no such | ||
- thing as pathname encoding translation. | ||
+Git is to some extent character encoding agnostic. | ||
- The contents of the blob objects are uninterpreted sequences | ||
of bytes. There is no encoding translation at the core | ||
level. | ||
- - The commit log messages are uninterpreted sequences of non-NUL | ||
- bytes. | ||
+ - Path names are encoded in UTF-8 normalization form C. This | ||
+ applies to tree objects, the index file, ref names, as well as | ||
+ path names in command line arguments, environment variables | ||
+ and config files (`.git/config` (see linkgit:git-config[1]), | ||
+ linkgit:gitignore[5], linkgit:gitattributes[5] and | ||
+ linkgit:gitmodules[5]). | ||
++ | ||
+Note that Git at the core level treats path names simply as | ||
+sequences of non-NUL bytes, there are no path name encoding | ||
+conversions (except on Mac and Windows). Therefore, using | ||
+non-ASCII path names will mostly work even on platforms and file | ||
+systems that use legacy extended ASCII encodings. However, | ||
+repositories created on such systems will not work properly on | ||
+UTF-8-based systems (e.g. Linux, Mac, Windows) and vice versa. | ||
+Additionally, many Git-based tools simply assume path names to | ||
+be UTF-8 and will fail to display other encodings correctly. | ||
+ | ||
+ - Commit log messages are typically encoded in UTF-8, but other | ||
+ extended ASCII encodings are also supported. This includes | ||
+ ISO-8859-x, CP125x and many others, but _not_ UTF-16/32, | ||
+ EBCDIC and CJK multi-byte encodings (GBK, Shift-JIS, Big5, | ||
+ EUC-x, CP9xx etc.). | ||
Although we encourage that the commit log messages are encoded | ||
in UTF-8, both the core and Git Porcelain are designed not to | ||
View
2
Documentation/pretty-formats.txt
@@ -139,7 +139,9 @@ The placeholders are: | ||
- '%f': sanitized subject line, suitable for a filename | ||
- '%b': body | ||
- '%B': raw body (unwrapped subject and body) | ||
+ifndef::git-rev-list[] | ||
- '%N': commit notes | ||
+endif::git-rev-list[] | ||
- '%GG': raw verification message from GPG for a signed commit | ||
- '%G?': show "G" for a Good signature, "B" for a Bad signature, "U" for a good, | ||
untrusted signature and "N" for no signature | ||
View
2
Documentation/pretty-options.txt
@@ -42,6 +42,7 @@ people using 80-column terminals. | ||
verbatim; this means that invalid sequences in the original | ||
commit may be copied to the output. | ||
+ifndef::git-rev-list[] | ||
--notes[=<ref>]:: | ||
Show the notes (see linkgit:git-notes[1]) that annotate the | ||
commit, when showing the commit log message. This is the default | ||
@@ -73,6 +74,7 @@ being displayed. Examples: "--notes=foo" will show only notes from | ||
--[no-]standard-notes:: | ||
These options are deprecated. Use the above --notes/--no-notes | ||
options instead. | ||
+endif::git-rev-list[] | ||
--show-signature:: | ||
Check the validity of a signed commit object by passing the signature | ||
View
7
Documentation/rev-list-options.txt
@@ -58,9 +58,11 @@ endif::git-rev-list[] | ||
more than one `--grep=<pattern>`, commits whose message | ||
matches any of the given patterns are chosen (but see | ||
`--all-match`). | ||
+ifndef::git-rev-list[] | ||
+ | ||
When `--show-notes` is in effect, the message from the notes is | ||
matched as if it were part of the log message. | ||
+endif::git-rev-list[] | ||
--all-match:: | ||
Limit the commits output to ones that match all given `--grep`, | ||
@@ -727,6 +729,11 @@ format, often found in email messages. | ||
+ | ||
`--date=raw` shows the date in the internal raw Git format `%s %z` format. | ||
+ | ||
+`--date=format:...` feeds the format `...` to your system `strftime`. | ||
+Use `--date=format:%c` to show the date in your system locale's | ||
+preferred format. See the `strftime` manual for a complete list of | ||
+format placeholders. | ||
++ | ||
`--date=default` shows timestamps in the original time zone | ||
(either committer's or author's). | ||
View
3
Documentation/technical/api-argv-array.txt
@@ -46,6 +46,9 @@ Functions | ||
Format a string and push it onto the end of the array. This is a | ||
convenience wrapper combining `strbuf_addf` and `argv_array_push`. | ||
+`argv_array_pushv`:: | ||
+ Push a null-terminated array of strings onto the end of the array. | ||
+ | ||
`argv_array_pop`:: | ||
Remove the final element from the array. If there are no | ||
elements in the array, do nothing. | ||
View
220
Documentation/technical/api-lockfile.txt
@@ -1,220 +0,0 @@ | ||
-lockfile API | ||
-============ | ||
- | ||
-The lockfile API serves two purposes: | ||
- | ||
-* Mutual exclusion and atomic file updates. When we want to change a | ||
- file, we create a lockfile `<filename>.lock`, write the new file | ||
- contents into it, and then rename the lockfile to its final | ||
- destination `<filename>`. We create the `<filename>.lock` file with | ||
- `O_CREAT|O_EXCL` so that we can notice and fail if somebody else has | ||
- already locked the file, then atomically rename the lockfile to its | ||
- final destination to commit the changes and unlock the file. | ||
- | ||
-* Automatic cruft removal. If the program exits after we lock a file | ||
- but before the changes have been committed, we want to make sure | ||
- that we remove the lockfile. This is done by remembering the | ||
- lockfiles we have created in a linked list and setting up an | ||
- `atexit(3)` handler and a signal handler that clean up the | ||
- lockfiles. This mechanism ensures that outstanding lockfiles are | ||
- cleaned up if the program exits (including when `die()` is called) | ||
- or if the program dies on a signal. | ||
- | ||
-Please note that lockfiles only block other writers. Readers do not | ||
-block, but they are guaranteed to see either the old contents of the | ||
-file or the new contents of the file (assuming that the filesystem | ||
-implements `rename(2)` atomically). | ||
- | ||
- | ||
-Calling sequence | ||
----------------- | ||
- | ||
-The caller: | ||
- | ||
-* Allocates a `struct lock_file` either as a static variable or on the | ||
- heap, initialized to zeros. Once you use the structure to call the | ||
- `hold_lock_file_*` family of functions, it belongs to the lockfile | ||
- subsystem and its storage must remain valid throughout the life of | ||
- the program (i.e. you cannot use an on-stack variable to hold this | ||
- structure). | ||
- | ||
-* Attempts to create a lockfile by passing that variable and the path | ||
- of the final destination (e.g. `$GIT_DIR/index`) to | ||
- `hold_lock_file_for_update` or `hold_lock_file_for_append`. | ||
- | ||
-* Writes new content for the destination file by either: | ||
- | ||
- * writing to the file descriptor returned by the `hold_lock_file_*` | ||
- functions (also available via `lock->fd`). | ||
- | ||
- * calling `fdopen_lock_file` to get a `FILE` pointer for the open | ||
- file and writing to the file using stdio. | ||
- | ||
-When finished writing, the caller can: | ||
- | ||
-* Close the file descriptor and rename the lockfile to its final | ||
- destination by calling `commit_lock_file` or `commit_lock_file_to`. | ||
- | ||
-* Close the file descriptor and remove the lockfile by calling | ||
- `rollback_lock_file`. | ||
- | ||
-* Close the file descriptor without removing or renaming the lockfile | ||
- by calling `close_lock_file`, and later call `commit_lock_file`, | ||
- `commit_lock_file_to`, `rollback_lock_file`, or `reopen_lock_file`. | ||
- | ||
-Even after the lockfile is committed or rolled back, the `lock_file` | ||
-object must not be freed or altered by the caller. However, it may be | ||
-reused; just pass it to another call of `hold_lock_file_for_update` or | ||
-`hold_lock_file_for_append`. | ||
- | ||
-If the program exits before you have called one of `commit_lock_file`, | ||
-`commit_lock_file_to`, `rollback_lock_file`, or `close_lock_file`, an | ||
-`atexit(3)` handler will close and remove the lockfile, rolling back | ||
-any uncommitted changes. | ||
- | ||
-If you need to close the file descriptor you obtained from a | ||
-`hold_lock_file_*` function yourself, do so by calling | ||
-`close_lock_file`. You should never call `close(2)` or `fclose(3)` | ||
-yourself! Otherwise the `struct lock_file` structure would still think | ||
-that the file descriptor needs to be closed, and a commit or rollback | ||
-would result in duplicate calls to `close(2)`. Worse yet, if you close | ||
-and then later open another file descriptor for a completely different | ||
-purpose, then a commit or rollback might close that unrelated file | ||
-descriptor. | ||
- | ||
- | ||
-Error handling | ||
--------------- | ||
- | ||
-The `hold_lock_file_*` functions return a file descriptor on success | ||
-or -1 on failure (unless `LOCK_DIE_ON_ERROR` is used; see below). On | ||
-errors, `errno` describes the reason for failure. Errors can be | ||
-reported by passing `errno` to one of the following helper functions: | ||
- | ||
-unable_to_lock_message:: | ||
- | ||
- Append an appropriate error message to a `strbuf`. | ||
- | ||
-unable_to_lock_error:: | ||
- | ||
- Emit an appropriate error message using `error()`. | ||
- | ||
-unable_to_lock_die:: | ||
- | ||
- Emit an appropriate error message and `die()`. | ||
- | ||
-Similarly, `commit_lock_file`, `commit_lock_file_to`, and | ||
-`close_lock_file` return 0 on success. On failure they set `errno` | ||
-appropriately, do their best to roll back the lockfile, and return -1. | ||
- | ||
- | ||
-Flags | ||
------ | ||
- | ||
-The following flags can be passed to `hold_lock_file_for_update` or | ||
-`hold_lock_file_for_append`: | ||
- | ||
-LOCK_NO_DEREF:: | ||
- | ||
- Usually symbolic links in the destination path are resolved | ||
- and the lockfile is created by adding ".lock" to the resolved | ||
- path. If `LOCK_NO_DEREF` is set, then the lockfile is created | ||
- by adding ".lock" to the path argument itself. This option is | ||
- used, for example, when locking a symbolic reference, which | ||
- for backwards-compatibility reasons can be a symbolic link | ||
- containing the name of the referred-to-reference. | ||
- | ||
-LOCK_DIE_ON_ERROR:: | ||
- | ||
- If a lock is already taken for the file, `die()` with an error | ||
- message. If this option is not specified, trying to lock a | ||
- file that is already locked returns -1 to the caller. | ||
- | ||
- | ||
-The functions | ||
-------------- | ||
- | ||
-hold_lock_file_for_update:: | ||
- | ||
- Take a pointer to `struct lock_file`, the path of the file to | ||
- be locked (e.g. `$GIT_DIR/index`) and a flags argument (see | ||
- above). Attempt to create a lockfile for the destination and | ||
- return the file descriptor for writing to the file. | ||
- | ||
-hold_lock_file_for_append:: | ||
- | ||
- Like `hold_lock_file_for_update`, but before returning copy | ||
- the existing contents of the file (if any) to the lockfile and | ||
- position its write pointer at the end of the file. | ||
- | ||
-fdopen_lock_file:: | ||
- | ||
- Associate a stdio stream with the lockfile. Return NULL | ||
- (*without* rolling back the lockfile) on error. The stream is | ||
- closed automatically when `close_lock_file` is called or when | ||
- the file is committed or rolled back. | ||
- | ||
-get_locked_file_path:: | ||
- | ||
- Return the path of the file that is locked by the specified | ||
- lock_file object. The caller must free the memory. | ||
- | ||
-commit_lock_file:: | ||
- | ||
- Take a pointer to the `struct lock_file` initialized with an | ||
- earlier call to `hold_lock_file_for_update` or | ||
- `hold_lock_file_for_append`, close the file descriptor, and | ||
- rename the lockfile to its final destination. Return 0 upon | ||
- success. On failure, roll back the lock file and return -1, | ||
- with `errno` set to the value from the failing call to | ||
- `close(2)` or `rename(2)`. It is a bug to call | ||
- `commit_lock_file` for a `lock_file` object that is not | ||
- currently locked. | ||
- | ||
-commit_lock_file_to:: | ||
- | ||
- Like `commit_lock_file()`, except that it takes an explicit | ||
- `path` argument to which the lockfile should be renamed. The | ||
- `path` must be on the same filesystem as the lock file. | ||
- | ||
-rollback_lock_file:: | ||
- | ||
- Take a pointer to the `struct lock_file` initialized with an | ||
- earlier call to `hold_lock_file_for_update` or | ||
- `hold_lock_file_for_append`, close the file descriptor and | ||
- remove the lockfile. It is a NOOP to call | ||
- `rollback_lock_file()` for a `lock_file` object that has | ||
- already been committed or rolled back. | ||
- | ||
-close_lock_file:: | ||
- | ||
- Take a pointer to the `struct lock_file` initialized with an | ||
- earlier call to `hold_lock_file_for_update` or | ||
- `hold_lock_file_for_append`. Close the file descriptor (and | ||
- the file pointer if it has been opened using | ||
- `fdopen_lock_file`). Return 0 upon success. On failure to | ||
- `close(2)`, return a negative value and roll back the lock | ||
- file. Usually `commit_lock_file`, `commit_lock_file_to`, or | ||
- `rollback_lock_file` should eventually be called if | ||
- `close_lock_file` succeeds. | ||
- | ||
-reopen_lock_file:: | ||
- | ||
- Re-open a lockfile that has been closed (using | ||
- `close_lock_file`) but not yet committed or rolled back. This | ||
- can be used to implement a sequence of operations like the | ||
- following: | ||
- | ||
- * Lock file. | ||
- | ||
- * Write new contents to lockfile, then `close_lock_file` to | ||
- cause the contents to be written to disk. | ||
- | ||
- * Pass the name of the lockfile to another program to allow it | ||
- (and nobody else) to inspect the contents you wrote, while | ||
- still holding the lock yourself. | ||
- | ||
- * `reopen_lock_file` to reopen the lockfile. Make further | ||
- updates to the contents. | ||
- | ||
- * `commit_lock_file` to make the final version permanent. |
View
19
Documentation/technical/api-parse-options.txt
@@ -168,6 +168,12 @@ There are some macros to easily define options: | ||
Introduce an option with integer argument. | ||
The integer is put into `int_var`. | ||
+`OPT_MAGNITUDE(short, long, &unsigned_long_var, description)`:: | ||
+ Introduce an option with a size argument. The argument must be a | ||
+ non-negative integer and may include a suffix of 'k', 'm' or 'g' to | ||
+ scale the provided value by 1024, 1024^2 or 1024^3 respectively. | ||
+ The scaled value is put into `unsigned_long_var`. | ||
+ | ||
`OPT_DATE(short, long, &int_var, description)`:: | ||
Introduce an option with date argument, see `approxidate()`. | ||
The timestamp is put into `int_var`. | ||
@@ -212,6 +218,19 @@ There are some macros to easily define options: | ||
Use it to hide deprecated options that are still to be recognized | ||
and ignored silently. | ||
+`OPT_PASSTHRU(short, long, &char_var, arg_str, description, flags)`:: | ||
+ Introduce an option that will be reconstructed into a char* string, | ||
+ which must be initialized to NULL. This is useful when you need to | ||
+ pass the command-line option to another command. Any previous value | ||
+ will be overwritten, so this should only be used for options where | ||
+ the last one specified on the command line wins. | ||
+ | ||
+`OPT_PASSTHRU_ARGV(short, long, &argv_array_var, arg_str, description, flags)`:: | ||
+ Introduce an option where all instances of it on the command-line will | ||
+ be reconstructed into an argv_array. This is useful when you need to | ||
+ pass the command-line option, which can be specified multiple times, | ||
+ to another command. | ||
+ | ||
The last element of the array must be `OPT_END()`. | ||
View
62
Documentation/technical/api-submodule-config.txt
@@ -0,0 +1,62 @@ | ||
+submodule config cache API | ||
+========================== | ||
+ | ||
+The submodule config cache API allows to read submodule | ||
+configurations/information from specified revisions. Internally | ||
+information is lazily read into a cache that is used to avoid | ||
+unnecessary parsing of the same .gitmodule files. Lookups can be done by | ||
+submodule path or name. | ||
+ | ||
+Usage | ||
+----- | ||
+ | ||
+To initialize the cache with configurations from the worktree the caller | ||
+typically first calls `gitmodules_config()` to read values from the | ||
+worktree .gitmodules and then to overlay the local git config values | ||
+`parse_submodule_config_option()` from the config parsing | ||
+infrastructure. | ||
+ | ||
+The caller can look up information about submodules by using the | ||
+`submodule_from_path()` or `submodule_from_name()` functions. They return | ||
+a `struct submodule` which contains the values. The API automatically | ||
+initializes and allocates the needed infrastructure on-demand. If the | ||
+caller does only want to lookup values from revisions the initialization | ||
+can be skipped. | ||
+ | ||
+If the internal cache might grow too big or when the caller is done with | ||
+the API, all internally cached values can be freed with submodule_free(). | ||
+ | ||
+Data Structures | ||
+--------------- | ||
+ | ||
+`struct submodule`:: | ||
+ | ||
+ This structure is used to return the information about one | ||
+ submodule for a certain revision. It is returned by the lookup | ||
+ functions. | ||
+ | ||
+Functions | ||
+--------- | ||
+ | ||
+`void submodule_free()`:: | ||
+ | ||
+ Use these to free the internally cached values. | ||
+ | ||
+`int parse_submodule_config_option(const char *var, const char *value)`:: | ||
+ | ||
+ Can be passed to the config parsing infrastructure to parse | ||
+ local (worktree) submodule configurations. | ||
+ | ||
+`const struct submodule *submodule_from_path(const unsigned char *commit_sha1, const char *path)`:: | ||
+ | ||
+ Lookup values for one submodule by its commit_sha1 and path. | ||
+ | ||
+`const struct submodule *submodule_from_name(const unsigned char *commit_sha1, const char *name)`:: | ||
+ | ||
+ The same as above but lookup by name. | ||
+ | ||
+If given the null_sha1 as commit_sha1 the local configuration of a | ||
+submodule will be returned (e.g. consolidated values from local git | ||
+configuration and the .gitmodules file in the worktree). | ||
+ | ||
+For an example usage see test-submodule-config.c. |
View
2
Documentation/technical/index-format.txt
@@ -275,7 +275,7 @@ Git index format | ||
- The directory name terminated by NUL. | ||
- - A number of untrached file/dir names terminated by NUL. | ||
+ - A number of untracked file/dir names terminated by NUL. | ||
The remaining data of each directory block is grouped by type: | ||
View
46
Documentation/technical/pack-protocol.txt
@@ -14,6 +14,14 @@ data. The protocol functions to have a server tell a client what is | ||
currently on the server, then for the two to negotiate the smallest amount | ||
of data to send in order to fully update one or the other. | ||
+pkt-line Format | ||
+--------------- | ||
+ | ||
+The descriptions below build on the pkt-line format described in | ||
+protocol-common.txt. When the grammar indicate `PKT-LINE(...)`, unless | ||
+otherwise noted the usual pkt-line LF rules apply: the sender SHOULD | ||
+include a LF, but the receiver MUST NOT complain if it is not present. | ||
+ | ||
Transports | ||
---------- | ||
There are three transports over which the packfile protocol is | ||
@@ -143,9 +151,6 @@ with the object name that each reference currently points to. | ||
003fe92df48743b7bc7d26bcaabfddde0a1e20cae47c refs/tags/v1.0^{} | ||
0000 | ||
-Server SHOULD terminate each non-flush line using LF ("\n") terminator; | ||
-client MUST NOT complain if there is no terminator. | ||
- | ||
The returned response is a pkt-line stream describing each ref and | ||
its current value. The stream MUST be sorted by name according to | ||
the C locale ordering. | ||
@@ -165,15 +170,15 @@ MUST peel the ref if it's an annotated tag. | ||
flush-pkt | ||
no-refs = PKT-LINE(zero-id SP "capabilities^{}" | ||
- NUL capability-list LF) | ||
+ NUL capability-list) | ||
list-of-refs = first-ref *other-ref | ||
first-ref = PKT-LINE(obj-id SP refname | ||
- NUL capability-list LF) | ||
+ NUL capability-list) | ||
other-ref = PKT-LINE(other-tip / other-peeled) | ||
- other-tip = obj-id SP refname LF | ||
- other-peeled = obj-id SP refname "^{}" LF | ||
+ other-tip = obj-id SP refname | ||
+ other-peeled = obj-id SP refname "^{}" | ||
shallow = PKT-LINE("shallow" SP obj-id) | ||
@@ -216,8 +221,8 @@ out of what the server said it could do with the first 'want' line. | ||
depth-request = PKT-LINE("deepen" SP depth) | ||
- first-want = PKT-LINE("want" SP obj-id SP capability-list LF) | ||
- additional-want = PKT-LINE("want" SP obj-id LF) | ||
+ first-want = PKT-LINE("want" SP obj-id SP capability-list) | ||
+ additional-want = PKT-LINE("want" SP obj-id) | ||
depth = 1*DIGIT | ||
---- | ||
@@ -284,7 +289,7 @@ so that there is always a block of 32 "in-flight on the wire" at a time. | ||
compute-end | ||
have-list = *have-line | ||
- have-line = PKT-LINE("have" SP obj-id LF) | ||
+ have-line = PKT-LINE("have" SP obj-id) | ||
compute-end = flush-pkt / PKT-LINE("done") | ||
---- | ||
@@ -348,10 +353,10 @@ Then the server will start sending its packfile data. | ||
---- | ||
server-response = *ack_multi ack / nak | ||
- ack_multi = PKT-LINE("ACK" SP obj-id ack_status LF) | ||
+ ack_multi = PKT-LINE("ACK" SP obj-id ack_status) | ||
ack_status = "continue" / "common" / "ready" | ||
- ack = PKT-LINE("ACK SP obj-id LF) | ||
- nak = PKT-LINE("NAK" LF) | ||
+ ack = PKT-LINE("ACK" SP obj-id) | ||
+ nak = PKT-LINE("NAK") | ||
---- | ||
A simple clone may look like this (with no 'have' lines): | ||
@@ -467,10 +472,10 @@ references. | ||
---- | ||
update-request = *shallow ( command-list | push-cert ) [packfile] | ||
- shallow = PKT-LINE("shallow" SP obj-id LF) | ||
+ shallow = PKT-LINE("shallow" SP obj-id) | ||
- command-list = PKT-LINE(command NUL capability-list LF) | ||
- *PKT-LINE(command LF) | ||
+ command-list = PKT-LINE(command NUL capability-list) | ||
+ *PKT-LINE(command) | ||
flush-pkt | ||
command = create / delete / update | ||
@@ -521,7 +526,8 @@ Push Certificate | ||
A push certificate begins with a set of header lines. After the | ||
header and an empty line, the protocol commands follow, one per | ||
-line. | ||
+line. Note that the the trailing LF in push-cert PKT-LINEs is _not_ | ||
+optional; it must be present. | ||
Currently, the following header fields are defined: | ||
@@ -560,12 +566,12 @@ update was successful, or 'ng [refname] [error]' if the update was not. | ||
1*(command-status) | ||
flush-pkt | ||
- unpack-status = PKT-LINE("unpack" SP unpack-result LF) | ||
+ unpack-status = PKT-LINE("unpack" SP unpack-result) | ||
unpack-result = "ok" / error-msg | ||
command-status = command-ok / command-fail | ||
- command-ok = PKT-LINE("ok" SP refname LF) | ||
- command-fail = PKT-LINE("ng" SP refname SP error-msg LF) | ||
+ command-ok = PKT-LINE("ok" SP refname) | ||
+ command-fail = PKT-LINE("ng" SP refname SP error-msg) | ||
error-msg = 1*(OCTECT) ; where not "ok" | ||
---- | ||
View
5
Documentation/technical/protocol-common.txt
@@ -62,7 +62,10 @@ A pkt-line MAY contain binary data, so implementors MUST ensure | ||
pkt-line parsing/formatting routines are 8-bit clean. | ||
A non-binary line SHOULD BE terminated by an LF, which if present | ||
-MUST be included in the total length. | ||
+MUST be included in the total length. Receivers MUST treat pkt-lines | ||
+with non-binary data the same whether or not they contain the trailing | ||
+LF (stripping the LF if present, and not complaining when it is | ||
+missing). | ||
The maximum length of a pkt-line's data component is 65520 bytes. | ||
Implementations MUST NOT send pkt-line whose length exceeds 65524 | ||
View
4
GIT-VERSION-GEN
@@ -1,7 +1,7 @@ | ||
#!/bin/sh | ||
GVF=GIT-VERSION-FILE | ||
-DEF_VER=v2.5.0 | ||
+DEF_VER=v2.6.0 | ||
LF=' | ||
' | ||
@@ -38,5 +38,3 @@ test "$VN" = "$VC" || { | ||
echo >&2 "GIT_VERSION = $VN" | ||
echo "GIT_VERSION = $VN" >$GVF | ||
} | ||
- | ||
- |
View
12
Makefile
@@ -467,7 +467,6 @@ TEST_PROGRAMS_NEED_X = | ||
# interactive shell sessions without exporting it. | ||
unexport CDPATH | ||
-SCRIPT_SH += git-am.sh | ||
SCRIPT_SH += git-bisect.sh | ||
SCRIPT_SH += git-difftool--helper.sh | ||
SCRIPT_SH += git-filter-branch.sh | ||
@@ -475,7 +474,6 @@ SCRIPT_SH += git-merge-octopus.sh | ||
SCRIPT_SH += git-merge-one-file.sh | ||
SCRIPT_SH += git-merge-resolve.sh | ||
SCRIPT_SH += git-mergetool.sh | ||
-SCRIPT_SH += git-pull.sh | ||
SCRIPT_SH += git-quiltimport.sh | ||
SCRIPT_SH += git-rebase.sh | ||
SCRIPT_SH += git-remote-testgit.sh | ||
@@ -595,6 +593,7 @@ TEST_PROGRAMS_NEED_X += test-sha1 | ||
TEST_PROGRAMS_NEED_X += test-sha1-array | ||
TEST_PROGRAMS_NEED_X += test-sigchain | ||
TEST_PROGRAMS_NEED_X += test-string-list | ||
+TEST_PROGRAMS_NEED_X += test-submodule-config | ||
TEST_PROGRAMS_NEED_X += test-subprocess | ||
TEST_PROGRAMS_NEED_X += test-svn-fe | ||
TEST_PROGRAMS_NEED_X += test-urlmatch-normalization | ||
@@ -763,6 +762,7 @@ LIB_OBJS += reachable.o | ||
LIB_OBJS += read-cache.o | ||
LIB_OBJS += reflog-walk.o | ||
LIB_OBJS += refs.o | ||
+LIB_OBJS += ref-filter.o | ||
LIB_OBJS += remote.o | ||
LIB_OBJS += replace_object.o | ||
LIB_OBJS += rerere.o | ||
@@ -785,8 +785,10 @@ LIB_OBJS += strbuf.o | ||
LIB_OBJS += streaming.o | ||
LIB_OBJS += string-list.o | ||
LIB_OBJS += submodule.o | ||
+LIB_OBJS += submodule-config.o | ||
LIB_OBJS += symlinks.o | ||
LIB_OBJS += tag.o | ||
+LIB_OBJS += tempfile.o | ||
LIB_OBJS += trace.o | ||
LIB_OBJS += trailer.o | ||
LIB_OBJS += transport.o | ||
@@ -813,6 +815,7 @@ LIB_OBJS += xdiff-interface.o | ||
LIB_OBJS += zlib.o | ||
BUILTIN_OBJS += builtin/add.o | ||
+BUILTIN_OBJS += builtin/am.o | ||
BUILTIN_OBJS += builtin/annotate.o | ||
BUILTIN_OBJS += builtin/apply.o | ||
BUILTIN_OBJS += builtin/archive.o | ||
@@ -878,6 +881,7 @@ BUILTIN_OBJS += builtin/pack-refs.o | ||
BUILTIN_OBJS += builtin/patch-id.o | ||
BUILTIN_OBJS += builtin/prune-packed.o | ||
BUILTIN_OBJS += builtin/prune.o | ||
+BUILTIN_OBJS += builtin/pull.o | ||
BUILTIN_OBJS += builtin/push.o | ||
BUILTIN_OBJS += builtin/read-tree.o | ||
BUILTIN_OBJS += builtin/receive-pack.o | ||
@@ -1696,10 +1700,10 @@ $(BUILT_INS): git$X | ||
ln -s $< $@ 2>/dev/null || \ | ||
cp $< $@ | ||
-common-cmds.h: generate-cmdlist.perl command-list.txt | ||
+common-cmds.h: generate-cmdlist.sh command-list.txt | ||
common-cmds.h: $(wildcard Documentation/git-*.txt) | ||
- $(QUIET_GEN)$(PERL_PATH) generate-cmdlist.perl command-list.txt > $@+ && mv $@+ $@ | ||
+ $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@ | ||
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\ | ||
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\ | ||
View
2
RelNotes
@@ -1 +1 @@ | ||
-Documentation/RelNotes/2.5.0.txt | ||
+Documentation/RelNotes/2.6.0.txt |
View
8
advice.c
@@ -96,6 +96,14 @@ void NORETURN die_resolve_conflict(const char *me) | ||
die("Exiting because of an unresolved conflict."); | ||
} | ||
+void NORETURN die_conclude_merge(void) | ||
+{ | ||
+ error(_("You have not concluded your merge (MERGE_HEAD exists).")); | ||
+ if (advice_resolve_conflict) | ||
+ advise(_("Please, commit your changes before you can merge.")); | ||
+ die(_("Exiting because of unfinished merge.")); | ||
+} | ||
+ | ||
void detach_advice(const char *new_name) | ||
{ | ||
const char fmt[] = | ||
View
1
advice.h
@@ -24,6 +24,7 @@ __attribute__((format (printf, 1, 2))) | ||
void advise(const char *advice, ...); | ||
int error_resolve_conflict(const char *me); | ||
extern void NORETURN die_resolve_conflict(const char *me); | ||
+void NORETURN die_conclude_merge(void); | ||
void detach_advice(const char *new_name); | ||
#endif /* ADVICE_H */ |
View
3
alias.c
@@ -5,7 +5,8 @@ char *alias_lookup(const char *alias) | ||
char *v = NULL; | ||
struct strbuf key = STRBUF_INIT; | ||
strbuf_addf(&key, "alias.%s", alias); | ||
- git_config_get_string(key.buf, &v); | ||
+ if (git_config_key_is_valid(key.buf)) | ||
+ git_config_get_string(key.buf, &v); | ||
strbuf_release(&key); | ||
return v; | ||
} | ||
View
99
archive-zip.c
@@ -16,7 +16,9 @@ static unsigned int zip_dir_size; | ||
static unsigned int zip_offset; | ||
static unsigned int zip_dir_offset; | ||
-static unsigned int zip_dir_entries; | ||
+static uint64_t zip_dir_entries; | ||
+ | ||
+static unsigned int max_creator_version; | ||
#define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024) | ||
#define ZIP_STREAM (1 << 3) | ||
@@ -86,6 +88,28 @@ struct zip_extra_mtime { | ||
unsigned char _end[1]; | ||
}; | ||
+struct zip64_dir_trailer { | ||
+ unsigned char magic[4]; | ||
+ unsigned char record_size[8]; | ||
+ unsigned char creator_version[2]; | ||
+ unsigned char version[2]; | ||
+ unsigned char disk[4]; | ||
+ unsigned char directory_start_disk[4]; | ||
+ unsigned char entries_on_this_disk[8]; | ||
+ unsigned char entries[8]; | ||
+ unsigned char size[8]; | ||
+ unsigned char offset[8]; | ||
+ unsigned char _end[1]; | ||
+}; | ||
+ | ||
+struct zip64_dir_trailer_locator { | ||
+ unsigned char magic[4]; | ||
+ unsigned char disk[4]; | ||
+ unsigned char offset[8]; | ||
+ unsigned char number_of_disks[4]; | ||
+ unsigned char _end[1]; | ||
+}; | ||
+ | ||
/* | ||
* On ARM, padding is added at the end of the struct, so a simple | ||
* sizeof(struct ...) reports two bytes more than the payload size | ||
@@ -98,6 +122,12 @@ struct zip_extra_mtime { | ||
#define ZIP_EXTRA_MTIME_SIZE offsetof(struct zip_extra_mtime, _end) | ||
#define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \ | ||
(ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags)) | ||
+#define ZIP64_DIR_TRAILER_SIZE offsetof(struct zip64_dir_trailer, _end) | ||
+#define ZIP64_DIR_TRAILER_RECORD_SIZE \ | ||
+ (ZIP64_DIR_TRAILER_SIZE - \ | ||
+ offsetof(struct zip64_dir_trailer, creator_version)) | ||
+#define ZIP64_DIR_TRAILER_LOCATOR_SIZE \ | ||
+ offsetof(struct zip64_dir_trailer_locator, _end) | ||
static void copy_le16(unsigned char *dest, unsigned int n) | ||
{ | ||
@@ -113,6 +143,31 @@ static void copy_le32(unsigned char *dest, unsigned int n) | ||
dest[3] = 0xff & (n >> 030); | ||
} | ||
+static void copy_le64(unsigned char *dest, uint64_t n) | ||
+{ | ||
+ dest[0] = 0xff & n; | ||
+ dest[1] = 0xff & (n >> 010); | ||
+ dest[2] = 0xff & (n >> 020); | ||
+ dest[3] = 0xff & (n >> 030); | ||
+ dest[4] = 0xff & (n >> 040); | ||
+ dest[5] = 0xff & (n >> 050); | ||
+ dest[6] = 0xff & (n >> 060); | ||
+ dest[7] = 0xff & (n >> 070); | ||
+} | ||
+ | ||
+static uint64_t clamp_max(uint64_t n, uint64_t max, int *clamped) | ||
+{ | ||
+ if (n <= max) | ||
+ return n; | ||
+ *clamped = 1; | ||
+ return max; | ||
+} | ||
+ | ||
+static void copy_le16_clamp(unsigned char *dest, uint64_t n, int *clamped) | ||
+{ | ||
+ copy_le16(dest, clamp_max(n, 0xffff, clamped)); | ||
+} | ||
+ | ||
static void *zlib_deflate_raw(void *data, unsigned long size, | ||
int compression_level, | ||
unsigned long *compressed_size) | ||
@@ -223,6 +278,7 @@ static int write_zip_entry(struct archiver_args *args, | ||
unsigned long size; | ||
int is_binary = -1; | ||
const char *path_without_prefix = path + args->baselen; | ||
+ unsigned int creator_version = 0; | ||
crc = crc32(0, NULL, 0); | ||
@@ -251,6 +307,8 @@ static int write_zip_entry(struct archiver_args *args, | ||
method = 0; | ||
attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : | ||
(mode & 0111) ? ((mode) << 16) : 0; | ||
+ if (S_ISLNK(mode) || (mode & 0111)) | ||
+ creator_version = 0x0317; | ||
if (S_ISREG(mode) && args->compression_level != 0 && size > 0) | ||
method = 8; | ||
@@ -279,6 +337,9 @@ static int write_zip_entry(struct archiver_args *args, | ||
sha1_to_hex(sha1)); | ||
} | ||
+ if (creator_version > max_creator_version) | ||
+ max_creator_version = creator_version; | ||
+ | ||
if (buffer && method == 8) { | ||
out = deflated = zlib_deflate_raw(buffer, size, | ||
args->compression_level, | ||
@@ -303,8 +364,7 @@ static int write_zip_entry(struct archiver_args *args, | ||
} | ||
copy_le32(dirent.magic, 0x02014b50); | ||
- copy_le16(dirent.creator_version, | ||
- S_ISLNK(mode) || (S_ISREG(mode) && (mode & 0111)) ? 0x0317 : 0); | ||
+ copy_le16(dirent.creator_version, creator_version); | ||
copy_le16(dirent.version, 10); | ||
copy_le16(dirent.flags, flags); | ||
copy_le16(dirent.compression_method, method); | ||
@@ -437,20 +497,49 @@ static int write_zip_entry(struct archiver_args *args, | ||
return 0; | ||
} | ||
+static void write_zip64_trailer(void) | ||
+{ | ||
+ struct zip64_dir_trailer trailer64; | ||
+ struct zip64_dir_trailer_locator locator64; | ||
+ | ||
+ copy_le32(trailer64.magic, 0x06064b50); | ||
+ copy_le64(trailer64.record_size, ZIP64_DIR_TRAILER_RECORD_SIZE); | ||
+ copy_le16(trailer64.creator_version, max_creator_version); | ||
+ copy_le16(trailer64.version, 45); | ||
+ copy_le32(trailer64.disk, 0); | ||
+ copy_le32(trailer64.directory_start_disk, 0); | ||
+ copy_le64(trailer64.entries_on_this_disk, zip_dir_entries); | ||
+ copy_le64(trailer64.entries, zip_dir_entries); | ||
+ copy_le64(trailer64.size, zip_dir_offset); | ||
+ copy_le64(trailer64.offset, zip_offset); | ||
+ | ||
+ copy_le32(locator64.magic, 0x07064b50); | ||
+ copy_le32(locator64.disk, 0); | ||
+ copy_le64(locator64.offset, zip_offset + zip_dir_offset); | ||
+ copy_le32(locator64.number_of_disks, 1); | ||
+ | ||
+ write_or_die(1, &trailer64, ZIP64_DIR_TRAILER_SIZE); | ||
+ write_or_die(1, &locator64, ZIP64_DIR_TRAILER_LOCATOR_SIZE); | ||
+} | ||
+ | ||
static void write_zip_trailer(const unsigned char *sha1) | ||
{ | ||
struct zip_dir_trailer trailer; | ||
+ int clamped = 0; | ||
copy_le32(trailer.magic, 0x06054b50); | ||
copy_le16(trailer.disk, 0); | ||
copy_le16(trailer.directory_start_disk, 0); | ||
- copy_le16(trailer.entries_on_this_disk, zip_dir_entries); | ||
- copy_le16(trailer.entries, zip_dir_entries); | ||
+ copy_le16_clamp(trailer.entries_on_this_disk, zip_dir_entries, | ||
+ &clamped); | ||
+ copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped); | ||
copy_le32(trailer.size, zip_dir_offset); | ||
copy_le32(trailer.offset, zip_offset); | ||
copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0); | ||
write_or_die(1, zip_dir, zip_dir_offset); | ||
+ if (clamped) | ||
+ write_zip64_trailer(); | ||
write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE); | ||
if (sha1) | ||
write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ); | ||
View
3
archive.c
@@ -1,4 +1,5 @@ | ||
#include "cache.h" | ||
+#include "refs.h" | ||
#include "commit.h" | ||
#include "tree-walk.h" | ||
#include "attr.h" | ||
@@ -33,7 +34,7 @@ static void format_subst(const struct commit *commit, | ||
char *to_free = NULL; | ||
struct strbuf fmt = STRBUF_INIT; | ||
struct pretty_print_context ctx = {0}; | ||
- ctx.date_mode = DATE_NORMAL; | ||
+ ctx.date_mode.type = DATE_NORMAL; | ||
ctx.abbrev = DEFAULT_ABBREV; | ||
if (src == buf->buf) | ||
View
6
argv-array.c
@@ -49,6 +49,12 @@ void argv_array_pushl(struct argv_array *array, ...) | ||
va_end(ap); | ||
} | ||
+void argv_array_pushv(struct argv_array *array, const char **argv) | ||
+{ | ||
+ for (; *argv; argv++) | ||
+ argv_array_push(array, *argv); | ||
+} | ||
+ | ||
void argv_array_pop(struct argv_array *array) | ||
{ | ||
if (!array->argc) | ||
View
1
argv-array.h
@@ -17,6 +17,7 @@ __attribute__((format (printf,2,3))) | ||
void argv_array_pushf(struct argv_array *, const char *fmt, ...); | ||
LAST_ARG_MUST_BE_NULL | ||
void argv_array_pushl(struct argv_array *, ...); | ||
+void argv_array_pushv(struct argv_array *, const char **); | ||
void argv_array_pop(struct argv_array *); | ||
void argv_array_clear(struct argv_array *); | ||
View
4
attr.c
@@ -490,6 +490,8 @@ static int git_attr_system(void) | ||
return !git_env_bool("GIT_ATTR_NOSYSTEM", 0); | ||
} | ||
+static GIT_PATH_FUNC(git_path_info_attributes, INFOATTRIBUTES_FILE) | ||
+ | ||
static void bootstrap_attr_stack(void) | ||
{ | ||
struct attr_stack *elem; | ||
@@ -531,7 +533,7 @@ static void bootstrap_attr_stack(void) | ||
debug_push(elem); | ||
} | ||
- elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1); | ||
+ elem = read_attr_from_file(git_path_info_attributes(), 1); | ||
if (!elem) | ||
elem = xcalloc(1, sizeof(*elem)); | ||
elem->origin = NULL; | ||
View
125
bisect.c
@@ -19,7 +19,9 @@ static struct object_id *current_bad_oid; | ||
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL}; | ||
static const char *argv_show_branch[] = {"show-branch", NULL, NULL}; | ||
-static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL}; | ||
+ | ||
+static const char *term_bad; | ||
+static const char *term_good; | ||
/* Remember to update object flag allocation in object.h */ | ||
#define COUNTED (1u<<16) | ||
@@ -403,15 +405,21 @@ struct commit_list *find_bisection(struct commit_list *list, | ||
static int register_ref(const char *refname, const struct object_id *oid, | ||
int flags, void *cb_data) | ||
{ | ||
- if (!strcmp(refname, "bad")) { | ||
+ struct strbuf good_prefix = STRBUF_INIT; | ||
+ strbuf_addstr(&good_prefix, term_good); | ||
+ strbuf_addstr(&good_prefix, "-"); | ||
+ | ||
+ if (!strcmp(refname, term_bad)) { | ||
current_bad_oid = xmalloc(sizeof(*current_bad_oid)); | ||
oidcpy(current_bad_oid, oid); | ||
- } else if (starts_with(refname, "good-")) { | ||
+ } else if (starts_with(refname, good_prefix.buf)) { | ||
sha1_array_append(&good_revs, oid->hash); | ||
} else if (starts_with(refname, "skip-")) { | ||
sha1_array_append(&skipped_revs, oid->hash); | ||
} | ||
+ strbuf_release(&good_prefix); | ||
+ | ||
return 0; | ||
} | ||
@@ -420,10 +428,13 @@ static int read_bisect_refs(void) | ||
return for_each_ref_in("refs/bisect/", register_ref, NULL); | ||
} | ||
+static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") | ||
+static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV") | ||
+ | ||
static void read_bisect_paths(struct argv_array *array) | ||
{ | ||
struct strbuf str = STRBUF_INIT; | ||
- const char *filename = git_path("BISECT_NAMES"); | ||
+ const char *filename = git_path_bisect_names(); | ||
FILE *fp = fopen(filename, "r"); | ||
if (!fp) | ||
@@ -634,7 +645,7 @@ static void exit_if_skipped_commits(struct commit_list *tried, | ||
return; | ||
printf("There are only 'skip'ped commits left to test.\n" | ||
- "The first bad commit could be any of:\n"); | ||
+ "The first %s commit could be any of:\n", term_bad); | ||
print_commit_list(tried, "%s\n", "%s\n"); | ||
if (bad) | ||
printf("%s\n", oid_to_hex(bad)); | ||
@@ -644,7 +655,7 @@ static void exit_if_skipped_commits(struct commit_list *tried, | ||
static int is_expected_rev(const struct object_id *oid) | ||
{ | ||
- const char *filename = git_path("BISECT_EXPECTED_REV"); | ||
+ const char *filename = git_path_bisect_expected_rev(); | ||
struct stat st; | ||
struct strbuf str = STRBUF_INIT; | ||
FILE *fp; | ||
@@ -666,34 +677,16 @@ static int is_expected_rev(const struct object_id *oid) | ||
return res; | ||
} | ||
-static void mark_expected_rev(char *bisect_rev_hex) | ||
-{ | ||
- int len = strlen(bisect_rev_hex); | ||
- const char *filename = git_path("BISECT_EXPECTED_REV"); | ||
- int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600); | ||
- | ||
- if (fd < 0) | ||
- die_errno("could not create file '%s'", filename); | ||
- | ||
- bisect_rev_hex[len] = '\n'; | ||
- write_or_die(fd, bisect_rev_hex, len + 1); | ||
- bisect_rev_hex[len] = '\0'; | ||
- | ||
- if (close(fd) < 0) | ||
- die("closing file %s: %s", filename, strerror(errno)); | ||
-} | ||
- | ||
-static int bisect_checkout(char *bisect_rev_hex, int no_checkout) | ||
+static int bisect_checkout(const unsigned char *bisect_rev, int no_checkout) | ||
{ | ||
+ char bisect_rev_hex[GIT_SHA1_HEXSZ + 1]; | ||
- mark_expected_rev(bisect_rev_hex); | ||
+ memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1); | ||
+ update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR); | ||
argv_checkout[2] = bisect_rev_hex; | ||
if (no_checkout) { | ||
- argv_update_ref[3] = bisect_rev_hex; | ||
- if (run_command_v_opt(argv_update_ref, RUN_GIT_CMD)) | ||
- die("update-ref --no-deref HEAD failed on %s", | ||
- bisect_rev_hex); | ||
+ update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR); | ||
} else { | ||
int res; | ||
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD); | ||
@@ -732,18 +725,24 @@ static void handle_bad_merge_base(void) | ||
if (is_expected_rev(current_bad_oid)) { | ||
char *bad_hex = oid_to_hex(current_bad_oid); | ||
char *good_hex = join_sha1_array_hex(&good_revs, ' '); | ||
- | ||
- fprintf(stderr, "The merge base %s is bad.\n" | ||
- "This means the bug has been fixed " | ||
- "between %s and [%s].\n", | ||
- bad_hex, bad_hex, good_hex); | ||
- | ||
+ if (!strcmp(term_bad, "bad") && !strcmp(term_good, "good")) { | ||
+ fprintf(stderr, "The merge base %s is bad.\n" | ||
+ "This means the bug has been fixed " | ||
+ "between %s and [%s].\n", | ||
+ bad_hex, bad_hex, good_hex); | ||
+ } else { | ||
+ fprintf(stderr, "The merge base %s is %s.\n" | ||
+ "This means the first '%s' commit is " | ||
+ "between %s and [%s].\n", | ||
+ bad_hex, term_bad, term_good, bad_hex, good_hex); | ||
+ } | ||
exit(3); | ||
} | ||
- fprintf(stderr, "Some good revs are not ancestor of the bad rev.\n" | ||
+ fprintf(stderr, "Some %s revs are not ancestor of the %s rev.\n" | ||
"git bisect cannot work properly in this case.\n" | ||
- "Maybe you mistake good and bad revs?\n"); | ||
+ "Maybe you mistook %s and %s revs?\n", | ||
+ term_good, term_bad, term_good, term_bad); | ||
exit(1); | ||
} | ||
@@ -755,10 +754,10 @@ static void handle_skipped_merge_base(const unsigned char *mb) | ||
warning("the merge base between %s and [%s] " | ||
"must be skipped.\n" | ||
- "So we cannot be sure the first bad commit is " | ||
+ "So we cannot be sure the first %s commit is " | ||
"between %s and %s.\n" | ||
"We continue anyway.", | ||
- bad_hex, good_hex, mb_hex, bad_hex); | ||
+ bad_hex, good_hex, term_bad, mb_hex, bad_hex); | ||
free(good_hex); | ||
} | ||
@@ -789,7 +788,7 @@ static void check_merge_bases(int no_checkout) | ||
handle_skipped_merge_base(mb); | ||
} else { | ||
printf("Bisecting: a merge base must be tested\n"); | ||
- exit(bisect_checkout(sha1_to_hex(mb), no_checkout)); | ||
+ exit(bisect_checkout(mb, no_checkout)); | ||
} | ||
} | ||
@@ -839,7 +838,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) | ||
int fd; | ||
if (!current_bad_oid) | ||
- die("a bad revision is needed"); | ||
+ die("a %s revision is needed", term_bad); | ||
/* Check if file BISECT_ANCESTORS_OK exists. */ | ||
if (!stat(filename, &st) && S_ISREG(st.st_mode)) | ||
@@ -890,6 +889,36 @@ static void show_diff_tree(const char *prefix, struct commit *commit) | ||
} | ||
/* | ||
+ * The terms used for this bisect session are stored in BISECT_TERMS. | ||
+ * We read them and store them to adapt the messages accordingly. | ||
+ * Default is bad/good. | ||
+ */ | ||
+void read_bisect_terms(const char **read_bad, const char **read_good) | ||
+{ | ||
+ struct strbuf str = STRBUF_INIT; | ||
+ const char *filename = git_path("BISECT_TERMS"); | ||
+ FILE *fp = fopen(filename, "r"); | ||
+ | ||
+ if (!fp) { | ||
+ if (errno == ENOENT) { | ||
+ *read_bad = "bad"; | ||
+ *read_good = "good"; | ||
+ return; | ||
+ } else { | ||
+ die("could not read file '%s': %s", filename, | ||
+ strerror(errno)); | ||
+ } | ||
+ } else { | ||
+ strbuf_getline(&str, fp, '\n'); | ||
+ *read_bad = strbuf_detach(&str, NULL); | ||
+ strbuf_getline(&str, fp, '\n'); | ||
+ *read_good = strbuf_detach(&str, NULL); | ||
+ } | ||
+ strbuf_release(&str); | ||
+ fclose(fp); | ||
+} | ||
+ | ||
+/* | ||
* We use the convention that exiting with an exit code 10 means that | ||
* the bisection process finished successfully. | ||
* In this case the calling shell script should exit 0. | ||
@@ -903,8 +932,8 @@ int bisect_next_all(const char *prefix, int no_checkout) | ||
struct commit_list *tried; | ||
int reaches = 0, all = 0, nr, steps; | ||
const unsigned char *bisect_rev; | ||
- char bisect_rev_hex[GIT_SHA1_HEXSZ + 1]; | ||
+ read_bisect_terms(&term_bad, &term_good); | ||
if (read_bisect_refs()) | ||
die("reading bisect refs failed"); | ||
@@ -926,8 +955,10 @@ int bisect_next_all(const char *prefix, int no_checkout) | ||
*/ | ||
exit_if_skipped_commits(tried, NULL); | ||
- printf("%s was both good and bad\n", | ||
- oid_to_hex(current_bad_oid)); | ||
+ printf("%s was both %s and %s\n", | ||
+ oid_to_hex(current_bad_oid), | ||
+ term_good, | ||
+ term_bad); | ||
exit(1); | ||
} | ||
@@ -938,11 +969,11 @@ int bisect_next_all(const char *prefix, int no_checkout) | ||
} | ||
bisect_rev = revs.commits->item->object.sha1; | ||
- memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1); | ||
if (!hashcmp(bisect_rev, current_bad_oid->hash)) { | ||
exit_if_skipped_commits(tried, current_bad_oid); | ||
- printf("%s is the first bad commit\n", bisect_rev_hex); | ||
+ printf("%s is the first %s commit\n", sha1_to_hex(bisect_rev), | ||
+ term_bad); | ||
show_diff_tree(prefix, revs.commits->item); | ||
/* This means the bisection process succeeded. */ | ||
exit(10); | ||
@@ -954,7 +985,7 @@ int bisect_next_all(const char *prefix, int no_checkout) | ||
"(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"), | ||
steps, (steps == 1 ? "" : "s")); | ||
- return bisect_checkout(bisect_rev_hex, no_checkout); | ||
+ return bisect_checkout(bisect_rev, no_checkout); | ||
} | ||
static inline int log2i(int n) | ||
View
2
bisect.h
@@ -26,4 +26,6 @@ extern int bisect_next_all(const char *prefix, int no_checkout); | ||
extern int estimate_bisect_steps(int all); | ||
+extern void read_bisect_terms(const char **bad, const char **good); | ||
+ | ||
#endif |
View
103
branch.c
@@ -302,11 +302,100 @@ void create_branch(const char *head, | ||
void remove_branch_state(void) | ||
{ | ||
- unlink(git_path("CHERRY_PICK_HEAD")); | ||
- unlink(git_path("REVERT_HEAD")); | ||
- unlink(git_path("MERGE_HEAD")); | ||
- unlink(git_path("MERGE_RR")); | ||
- unlink(git_path("MERGE_MSG")); | ||
- unlink(git_path("MERGE_MODE")); | ||
- unlink(git_path("SQUASH_MSG")); | ||
+ unlink(git_path_cherry_pick_head()); | ||
+ unlink(git_path_revert_head()); | ||
+ unlink(git_path_merge_head()); | ||
+ unlink(git_path_merge_rr()); | ||
+ unlink(git_path_merge_msg()); | ||
+ unlink(git_path_merge_mode()); | ||
+ unlink(git_path_squash_msg()); | ||
+} | ||
+ | ||
+static char *find_linked_symref(const char *symref, const char *branch, | ||
+ const char *id) | ||
+{ | ||
+ struct strbuf sb = STRBUF_INIT; | ||
+ struct strbuf path = STRBUF_INIT; | ||
+ struct strbuf gitdir = STRBUF_INIT; | ||
+ char *existing = NULL; | ||
+ | ||
+ /* | ||
+ * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside | ||
+ * $GIT_DIR so resolve_ref_unsafe() won't work (it uses | ||
+ * git_path). Parse the ref ourselves. | ||
+ */ | ||
+ if (id) | ||
+ strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref); | ||
+ else | ||
+ strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref); | ||
+ | ||
+ if (!strbuf_readlink(&sb, path.buf, 0)) { | ||
+ if (!starts_with(sb.buf, "refs/") || | ||
+ check_refname_format(sb.buf, 0)) | ||
+ goto done; | ||
+ } else if (strbuf_read_file(&sb, path.buf, 0) >= 0 && | ||
+ starts_with(sb.buf, "ref:")) { | ||
+ strbuf_remove(&sb, 0, strlen("ref:")); | ||
+ strbuf_trim(&sb); | ||
+ } else | ||
+ goto done; | ||
+ if (strcmp(sb.buf, branch)) | ||
+ goto done; | ||
+ if (id) { | ||
+ strbuf_reset(&path); | ||
+ strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id); | ||
+ if (strbuf_read_file(&gitdir, path.buf, 0) <= 0) | ||
+ goto done; | ||
+ strbuf_rtrim(&gitdir); | ||
+ } else | ||
+ strbuf_addstr(&gitdir, get_git_common_dir()); | ||
+ strbuf_strip_suffix(&gitdir, ".git"); | ||
+ | ||
+ existing = strbuf_detach(&gitdir, NULL); | ||
+done: | ||
+ strbuf_release(&path); | ||
+ strbuf_release(&sb); | ||
+ strbuf_release(&gitdir); | ||
+ | ||
+ return existing; | ||
+} | ||
+ | ||
+char *find_shared_symref(const char *symref, const char *target) | ||
+{ | ||
+ struct strbuf path = STRBUF_INIT; | ||
+ DIR *dir; | ||
+ struct dirent *d; | ||
+ char *existing; | ||
+ | ||
+ if ((existing = find_linked_symref(symref, target, NULL))) | ||
+ return existing; | ||
+ | ||
+ strbuf_addf(&path, "%s/worktrees", get_git_common_dir()); | ||
+ dir = opendir(path.buf); | ||
+ strbuf_release(&path); | ||
+ if (!dir) | ||
+ return NULL; | ||
+ | ||
+ while ((d = readdir(dir)) != NULL) { | ||
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) | ||
+ continue; | ||
+ existing = find_linked_symref(symref, target, d->d_name); | ||
+ if (existing) | ||
+ goto done; | ||
+ } | ||
+done: | ||
+ closedir(dir); | ||
+ | ||
+ return existing; | ||
+} | ||
+ | ||
+void die_if_checked_out(const char *branch) | ||
+{ | ||
+ char *existing; | ||
+ | ||
+ existing = find_shared_symref("HEAD", branch); | ||
+ if (existing) { | ||
+ skip_prefix(branch, "refs/heads/", &branch); | ||
+ die(_("'%s' is already checked out at '%s'"), branch, existing); | ||
+ } | ||
} |
View
15
branch.h
@@ -52,4 +52,19 @@ extern void install_branch_config(int flag, const char *local, const char *origi | ||
*/ | ||
extern int read_branch_desc(struct strbuf *, const char *branch_name); | ||
+/* | ||
+ * Check if a branch is checked out in the main worktree or any linked | ||
+ * worktree and die (with a message describing its checkout location) if | ||
+ * it is. | ||
+ */ | ||
+extern void die_if_checked_out(const char *branch); | ||
+ | ||
+/* | ||
+ * Check if a per-worktree symref points to a ref in the main worktree | ||
+ * or any linked worktree, and return the path to the exising worktree | ||
+ * if it is. Returns NULL if there is no existing ref. The caller is | ||
+ * responsible for freeing the returned path. | ||
+ */ | ||
+extern char *find_shared_symref(const char *symref, const char *target); | ||
+ | ||
#endif |
View
2
builtin.h
@@ -30,6 +30,7 @@ extern int textconv_object(const char *path, unsigned mode, const unsigned char | ||
extern int is_builtin(const char *s); | ||
extern int cmd_add(int argc, const char **argv, const char *prefix); | ||
+extern int cmd_am(int argc, const char **argv, const char *prefix); | ||
extern int cmd_annotate(int argc, const char **argv, const char *prefix); | ||
extern int cmd_apply(int argc, const char **argv, const char *prefix); | ||
extern int cmd_archive(int argc, const char **argv, const char *prefix); | ||
@@ -98,6 +99,7 @@ extern int cmd_pack_redundant(int argc, const char **argv, const char *prefix); | ||
extern int cmd_patch_id(int argc, const char **argv, const char *prefix); | ||
extern int cmd_prune(int argc, const char **argv, const char *prefix); | ||
extern int cmd_prune_packed(int argc, const char **argv, const char *prefix); | ||
+extern int cmd_pull(int argc, const char **argv, const char *prefix); | ||
extern int cmd_push(int argc, const char **argv, const char *prefix); | ||
extern int cmd_read_tree(int argc, const char **argv, const char *prefix); | ||
extern int cmd_receive_pack(int argc, const char **argv, const char *prefix); | ||
View
2
builtin/add.c
@@ -375,7 +375,6 @@ int cmd_add(int argc, const char **argv, const char *prefix) | ||
if (add_new_files) { | ||
int baselen; | ||
- struct pathspec empty_pathspec; | ||
/* Set up the default git porcelain excludes */ | ||
memset(&dir, 0, sizeof(dir)); | ||
@@ -384,7 +383,6 @@ int cmd_add(int argc, const char **argv, const char *prefix) | ||
setup_standard_excludes(&dir); | ||
} | ||
- memset(&empty_pathspec, 0, sizeof(empty_pathspec)); | ||
/* This picks up the paths that are not tracked */ | ||
baselen = fill_directory(&dir, &pathspec); | ||
if (pathspec.nr) | ||
View
2,411
builtin/am.c
2,411 additions,
0 deletions
not shown because the diff is too large. Please use a local Git client to view these changes.
View
2
builtin/apply.c
@@ -785,7 +785,7 @@ static int guess_p_value(const char *nameline) | ||
} | ||
/* | ||
- * Does the ---/+++ line has the POSIX timestamp after the last HT? | ||
+ * Does the ---/+++ line have the POSIX timestamp after the last HT? | ||
* GNU diff puts epoch there to signal a creation/deletion event. Is | ||
* this such a timestamp? | ||
*/ | ||
View
21
builtin/blame.c
@@ -6,6 +6,7 @@ | ||
*/ | ||
#include "cache.h" | ||
+#include "refs.h" | ||
#include "builtin.h" | ||
#include "blob.h" | ||
#include "commit.h" | ||
@@ -50,7 +51,7 @@ static int xdl_opts; | ||
static int abbrev = -1; | ||
static int no_whole_file_rename; | ||
-static enum date_mode blame_date_mode = DATE_ISO8601; | ||
+static struct date_mode blame_date_mode = { DATE_ISO8601 }; | ||
static size_t blame_date_width; | ||
static struct string_list mailmap; | ||
@@ -1827,7 +1828,7 @@ static const char *format_time(unsigned long time, const char *tz_str, | ||
size_t time_width; | ||
int tz; | ||
tz = atoi(tz_str); | ||
- time_str = show_date(time, tz, blame_date_mode); | ||
+ time_str = show_date(time, tz, &blame_date_mode); | ||
strbuf_addstr(&time_buf, time_str); | ||
/* | ||
* Add space paddings to time_buf to display a fixed width | ||
@@ -2187,7 +2188,7 @@ static int git_blame_config(const char *var, const char *value, void *cb) | ||
if (!strcmp(var, "blame.date")) { | ||
if (!value) | ||
return config_error_nonbool(var); | ||
- blame_date_mode = parse_date_format(value); | ||
+ parse_date_format(value, &blame_date_mode); | ||
return 0; | ||
} | ||
@@ -2226,20 +2227,19 @@ static struct commit_list **append_parent(struct commit_list **tail, const unsig | ||
static void append_merge_parents(struct commit_list **tail) | ||
{ | ||
int merge_head; | ||
- const char *merge_head_file = git_path("MERGE_HEAD"); | ||
struct strbuf line = STRBUF_INIT; | ||
- merge_head = open(merge_head_file, O_RDONLY); | ||
+ merge_head = open(git_path_merge_head(), O_RDONLY); | ||
if (merge_head < 0) { | ||
if (errno == ENOENT) | ||
return; | ||
- die("cannot open '%s' for reading", merge_head_file); | ||
+ die("cannot open '%s' for reading", git_path_merge_head()); | ||
} | ||
while (!strbuf_getwholeline_fd(&line, merge_head, '\n')) { | ||
unsigned char sha1[20]; | ||
if (line.len < 40 || get_sha1_hex(line.buf, sha1)) | ||
- die("unknown line in '%s': %s", merge_head_file, line.buf); | ||
+ die("unknown line in '%s': %s", git_path_merge_head(), line.buf); | ||
tail = append_parent(tail, sha1); | ||
} | ||
close(merge_head); | ||
@@ -2569,13 +2569,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix) | ||
if (cmd_is_annotate) { | ||
output_option |= OUTPUT_ANNOTATE_COMPAT; | ||
- blame_date_mode = DATE_ISO8601; | ||
+ blame_date_mode.type = DATE_ISO8601; | ||
} else { | ||
blame_date_mode = revs.date_mode; | ||
} | ||
/* The maximum width used to show the dates */ | ||
- switch (blame_date_mode) { | ||
+ switch (blame_date_mode.type) { | ||
case DATE_RFC2822: | ||
blame_date_width = sizeof("Thu, 19 Oct 2006 16:00:04 -0700"); | ||
break; | ||
@@ -2604,6 +2604,9 @@ int cmd_blame(int argc, const char **argv, const char *prefix) | ||
case DATE_NORMAL: | ||
blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700"); | ||
break; | ||
+ case DATE_STRFTIME: | ||
+ blame_date_width = strlen(show_date(0, 0, &blame_date_mode)) + 1; /* add the null */ | ||
+ break; | ||
} | ||
blame_date_width -= 1; /* strip the null */ | ||
View
7
builtin/branch.c
@@ -160,7 +160,7 @@ static int branch_merged(int kind, const char *name, | ||
} | ||
static int check_branch_commit(const char *branchname, const char *refname, | ||
- unsigned char *sha1, struct commit *head_rev, | ||
+ const unsigned char *sha1, struct commit *head_rev, | ||
int kinds, int force) | ||
{ | ||
struct commit *rev = lookup_commit_reference(sha1); | ||
@@ -253,7 +253,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, | ||
continue; | ||
} | ||
- if (delete_ref(name, sha1, REF_NODEREF)) { | ||
+ if (delete_ref(name, is_null_sha1(sha1) ? NULL : sha1, | ||
+ REF_NODEREF)) { | ||
error(remote_branch | ||
? _("Error deleting remote-tracking branch '%s'") | ||
: _("Error deleting branch '%s'"), | ||
@@ -775,7 +776,7 @@ static int edit_branch_description(const char *branch_name) | ||
" %s\n" | ||
"Lines starting with '%c' will be stripped.\n", | ||
branch_name, comment_line_char); | ||
- if (write_file(git_path(edit_description), 0, "%s", buf.buf)) { | ||
+ if (write_file_gently(git_path(edit_description), "%s", buf.buf)) { | ||
strbuf_release(&buf); | ||
return error(_("could not write branch description template: %s"), | ||
strerror(errno)); | ||
View
132
builtin/cat-file.c
@@ -9,6 +9,16 @@ | ||
#include "userdiff.h" | ||
#include "streaming.h" | ||
#include "tree-walk.h" | ||
+#include "sha1-array.h" | ||
+ | ||
+struct batch_options { | ||
+ int enabled; | ||
+ int follow_symlinks; | ||
+ int print_contents; | ||
+ int buffer_output; | ||
+ int all_objects; | ||
+ const char *format; | ||
+}; | ||
static int cat_one_file(int opt, const char *exp_type, const char *obj_name, | ||
int unknown_type) | ||
@@ -204,14 +214,25 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data) | ||
return end - start + 1; | ||
} | ||
-static void print_object_or_die(int fd, struct expand_data *data) | ||
+static void batch_write(struct batch_options *opt, const void *data, int len) | ||
+{ | ||
+ if (opt->buffer_output) { | ||
+ if (fwrite(data, 1, len, stdout) != len) | ||
+ die_errno("unable to write to stdout"); | ||
+ } else | ||
+ write_or_die(1, data, len); | ||
+} | ||
+ | ||
+static void print_object_or_die(struct batch_options *opt, struct expand_data *data) | ||
{ | ||
const unsigned char *sha1 = data->sha1; | ||
assert(data->info.typep); | ||
if (data->type == OBJ_BLOB) { | ||
- if (stream_blob_to_fd(fd, sha1, NULL, 0) < 0) | ||
+ if (opt->buffer_output) | ||
+ fflush(stdout); | ||
+ if (stream_blob_to_fd(1, sha1, NULL, 0) < 0) | ||
die("unable to stream %s to stdout", sha1_to_hex(sha1)); | ||
} | ||
else { | ||
@@ -227,29 +248,40 @@ static void print_object_or_die(int fd, struct expand_data *data) | ||
if (data->info.sizep && size != data->size) | ||
die("object %s changed size!?", sha1_to_hex(sha1)); | ||
- write_or_die(fd, contents, size); | ||
+ batch_write(opt, contents, size); | ||
free(contents); | ||
} | ||
} | ||
-struct batch_options { | ||
- int enabled; | ||
- int follow_symlinks; | ||
- int print_contents; | ||
- const char *format; | ||
-}; | ||
- | ||
-static int batch_one_object(const char *obj_name, struct batch_options *opt, | ||
- struct expand_data *data) | ||
+static void batch_object_write(const char *obj_name, struct batch_options *opt, | ||
+ struct expand_data *data) | ||
{ | ||
struct strbuf buf = STRBUF_INIT; | ||
+ | ||
+ if (sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { | ||
+ printf("%s missing\n", obj_name ? obj_name : sha1_to_hex(data->sha1)); | ||
+ fflush(stdout); | ||
+ return; | ||
+ } | ||
+ | ||
+ strbuf_expand(&buf, opt->format, expand_format, data); | ||
+ strbuf_addch(&buf, '\n'); | ||
+ batch_write(opt, buf.buf, buf.len); | ||
+ strbuf_release(&buf); | ||
+ | ||
+ if (opt->print_contents) { | ||
+ print_object_or_die(opt, data); | ||
+ batch_write(opt, "\n", 1); | ||
+ } | ||
+} | ||
+ | ||
+static void batch_one_object(const char *obj_name, struct batch_options *opt, | ||
+ struct expand_data *data) | ||
+{ | ||
struct object_context ctx; | ||
int flags = opt->follow_symlinks ? GET_SHA1_FOLLOW_SYMLINKS : 0; | ||
enum follow_symlinks_result result; | ||
- if (!obj_name) | ||
- return 1; | ||
- | ||
result = get_sha1_with_context(obj_name, flags, data->sha1, &ctx); | ||
if (result != FOUND) { | ||
switch (result) { | ||
@@ -274,7 +306,7 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt, | ||
break; | ||
} | ||
fflush(stdout); | ||
- return 0; | ||
+ return; | ||
} | ||
if (ctx.mode == 0) { | ||
@@ -282,24 +314,38 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt, | ||
(uintmax_t)ctx.symlink_path.len, | ||
ctx.symlink_path.buf); | ||
fflush(stdout); | ||
- return 0; | ||
+ return; | ||
} | ||
- if (sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { | ||
- printf("%s missing\n", obj_name); | ||
- fflush(stdout); | ||
- return 0; | ||
- } | ||
+ batch_object_write(obj_name, opt, data); | ||
+} | ||
- strbuf_expand(&buf, opt->format, expand_format, data); | ||
- strbuf_addch(&buf, '\n'); | ||
- write_or_die(1, buf.buf, buf.len); | ||
- strbuf_release(&buf); | ||
+struct object_cb_data { | ||
+ struct batch_options *opt; | ||
+ struct expand_data *expand; | ||
+}; | ||
- if (opt->print_contents) { | ||
- print_object_or_die(1, data); | ||
- write_or_die(1, "\n", 1); | ||
- } | ||
+static void batch_object_cb(const unsigned char sha1[20], void *vdata) | ||
+{ | ||
+ struct object_cb_data *data = vdata; | ||
+ hashcpy(data->expand->sha1, sha1); | ||
+ batch_object_write(NULL, data->opt, data->expand); | ||
+} | ||
+ | ||
+static int batch_loose_object(const unsigned char *sha1, | ||
+ const char *path, | ||
+ void *data) | ||
+{ | ||
+ sha1_array_append(data, sha1); | ||
+ return 0; | ||
+} | ||
+ | ||
+static int batch_packed_object(const unsigned char *sha1, | ||
+ struct packed_git *pack, | ||
+ uint32_t pos, | ||
+ void *data) | ||
+{ | ||
+ sha1_array_append(data, sha1); | ||
return 0; | ||
} | ||
@@ -330,6 +376,21 @@ static int batch_objects(struct batch_options *opt) | ||
if (opt->print_contents) | ||
data.info.typep = &data.type; | ||
+ if (opt->all_objects) { | ||
+ struct sha1_array sa = SHA1_ARRAY_INIT; | ||
+ struct object_cb_data cb; | ||
+ | ||
+ for_each_loose_object(batch_loose_object, &sa, 0); | ||
+ for_each_packed_object(batch_packed_object, &sa, 0); | ||
+ | ||
+ cb.opt = opt; | ||
+ cb.expand = &data; | ||
+ sha1_array_for_each_unique(&sa, batch_object_cb, &cb); | ||
+ | ||
+ sha1_array_clear(&sa); | ||
+ return 0; | ||
+ } | ||
+ | ||
/* | ||
* We are going to call get_sha1 on a potentially very large number of | ||
* objects. In most large cases, these will be actual object sha1s. The | ||
@@ -355,9 +416,7 @@ static int batch_objects(struct batch_options *opt) | ||
data.rest = p; | ||
} | ||
- retval = batch_one_object(buf.buf, opt, &data); | ||
- if (retval) | ||
- break; | ||
+ batch_one_object(buf.buf, opt, &data); | ||
} | ||
strbuf_release(&buf); | ||
@@ -412,8 +471,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) | ||
OPT_CMDMODE('p', NULL, &opt, N_("pretty-print object's content"), 'p'), | ||
OPT_CMDMODE(0, "textconv", &opt, | ||
N_("for blob objects, run textconv on object's content"), 'c'), | ||
- OPT_BOOL( 0, "allow-unknown-type", &unknown_type, | ||
+ OPT_BOOL(0, "allow-unknown-type", &unknown_type, | ||
N_("allow -s and -t to work with broken/corrupt objects")), | ||
+ OPT_BOOL(0, "buffer", &batch.buffer_output, N_("buffer --batch output")), | ||
{ OPTION_CALLBACK, 0, "batch", &batch, "format", | ||
N_("show info and content of objects fed from the standard input"), | ||
PARSE_OPT_OPTARG, batch_option_callback }, | ||
@@ -422,6 +482,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) | ||
PARSE_OPT_OPTARG, batch_option_callback }, | ||
OPT_BOOL(0, "follow-symlinks", &batch.follow_symlinks, | ||
N_("follow in-tree symlinks (used with --batch or --batch-check)")), | ||
+ OPT_BOOL(0, "batch-all-objects", &batch.all_objects, | ||
+ N_("show all objects with --batch or --batch-check")), | ||
OPT_END() | ||
}; | ||
@@ -446,7 +508,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) | ||
usage_with_options(cat_file_usage, options); | ||
} | ||
- if (batch.follow_symlinks && !batch.enabled) { | ||
+ if ((batch.follow_symlinks || batch.all_objects) && !batch.enabled) { | ||
usage_with_options(cat_file_usage, options); | ||
} | ||
View
107
builtin/checkout.c
@@ -18,6 +18,7 @@ | ||
#include "xdiff-interface.h" | ||
#include "ll-merge.h" | ||
#include "resolve-undo.h" | ||
+#include "submodule-config.h" | ||
#include "submodule.h" | ||
static const char * const checkout_usage[] = { | ||
@@ -48,8 +49,6 @@ struct checkout_opts { | ||
const char *prefix; | ||
struct pathspec pathspec; | ||
struct tree *source_tree; | ||
- | ||
- int new_worktree_mode; | ||
}; | ||
static int post_checkout_hook(struct commit *old, struct commit *new, | ||
@@ -282,7 +281,7 @@ static int checkout_paths(const struct checkout_opts *opts, | ||
if (opts->source_tree) | ||
read_tree_some(opts->source_tree, &opts->pathspec); | ||
- ps_matched = xcalloc(1, opts->pathspec.nr); | ||
+ ps_matched = xcalloc(opts->pathspec.nr, 1); | ||
/* | ||
* Make sure all pathspecs participated in locating the paths | ||
@@ -509,7 +508,7 @@ static int merge_working_tree(const struct checkout_opts *opts, | ||
topts.dir->flags |= DIR_SHOW_IGNORED; | ||
setup_standard_excludes(topts.dir); | ||
} | ||
- tree = parse_tree_indirect(old->commit && !opts->new_worktree_mode ? | ||
+ tree = parse_tree_indirect(old->commit ? | ||
old->commit->object.sha1 : | ||
EMPTY_TREE_SHA1_BIN); | ||
init_tree_desc(&trees[0], tree->buffer, tree->size); | ||
@@ -612,22 +611,20 @@ static void update_refs_for_switch(const struct checkout_opts *opts, | ||
if (opts->new_branch) { | ||
if (opts->new_orphan_branch) { | ||
if (opts->new_branch_log && !log_all_ref_updates) { | ||
- int temp; | ||
- struct strbuf log_file = STRBUF_INIT; | ||
int ret; | ||
- const char *ref_name; | ||
- | ||
- ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch); | ||
- temp = log_all_ref_updates; | ||
- log_all_ref_updates = 1; | ||
- ret = log_ref_setup(ref_name, &log_file); | ||
- log_all_ref_updates = temp; | ||
- strbuf_release(&log_file); | ||
+ char *refname; | ||
+ struct strbuf err = STRBUF_INIT; | ||
+ | ||
+ refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch); | ||
+ ret = safe_create_reflog(refname, 1, &err); | ||
+ free(refname); | ||
if (ret) { | ||
- fprintf(stderr, _("Can not do reflog for '%s'\n"), | ||
- opts->new_orphan_branch); | ||
+ fprintf(stderr, _("Can not do reflog for '%s': %s\n"), | ||
+ opts->new_orphan_branch, err.buf); | ||
+ strbuf_release(&err); | ||
return; | ||
} | ||
+ strbuf_release(&err); | ||
} | ||
} | ||
else | ||
@@ -832,8 +829,7 @@ static int switch_branches(const struct checkout_opts *opts, | ||
return ret; | ||
} | ||
- if (!opts->quiet && !old.path && old.commit && | ||
- new->commit != old.commit && !opts->new_worktree_mode) | ||
+ if (!opts->quiet && !old.path && old.commit && new->commit != old.commit) | ||
orphaned_commit_warning(old.commit, new->commit); | ||
update_refs_for_switch(opts, &old, new); | ||
@@ -898,71 +894,6 @@ static const char *unique_tracking_name(const char *name, unsigned char *sha1) | ||
return NULL; | ||
} | ||
-static void check_linked_checkout(struct branch_info *new, const char *id) | ||
-{ | ||
- struct strbuf sb = STRBUF_INIT; | ||
- struct strbuf path = STRBUF_INIT; | ||
- struct strbuf gitdir = STRBUF_INIT; | ||
- const char *start, *end; | ||
- | ||
- if (id) | ||
- strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id); | ||
- else | ||
- strbuf_addf(&path, "%s/HEAD", get_git_common_dir()); | ||
- | ||
- if (strbuf_read_file(&sb, path.buf, 0) < 0 || | ||
- !skip_prefix(sb.buf, "ref:", &start)) | ||
- goto done; | ||
- while (isspace(*start)) | ||
- start++; | ||
- end = start; | ||
- while (*end && !isspace(*end)) | ||
- end++; | ||
- if (strncmp(start, new->path, end - start) || new->path[end - start] != '\0') | ||
- goto done; | ||
- if (id) { | ||
- strbuf_reset(&path); | ||
- strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id); | ||
- if (strbuf_read_file(&gitdir, path.buf, 0) <= 0) | ||
- goto done; | ||
- strbuf_rtrim(&gitdir); | ||
- } else | ||
- strbuf_addstr(&gitdir, get_git_common_dir()); | ||
- die(_("'%s' is already checked out at '%s'"), new->name, gitdir.buf); | ||
-done: | ||
- strbuf_release(&path); | ||
- strbuf_release(&sb); | ||
- strbuf_release(&gitdir); | ||
-} | ||
- | ||
-static void check_linked_checkouts(struct branch_info *new) | ||
-{ | ||
- struct strbuf path = STRBUF_INIT; | ||
- DIR *dir; | ||
- struct dirent *d; | ||
- | ||
- strbuf_addf(&path, "%s/worktrees", get_git_common_dir()); | ||
- if ((dir = opendir(path.buf)) == NULL) { | ||
- strbuf_release(&path); | ||
- return; | ||
- } | ||
- | ||
- /* | ||
- * $GIT_COMMON_DIR/HEAD is practically outside | ||
- * $GIT_DIR so resolve_ref_unsafe() won't work (it | ||
- * uses git_path). Parse the ref ourselves. | ||
- */ | ||
- check_linked_checkout(new, NULL); | ||
- | ||
- while ((d = readdir(dir)) != NULL) { | ||
- if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) | ||
- continue; | ||
- check_linked_checkout(new, d->d_name); | ||
- } | ||
- strbuf_release(&path); | ||
- closedir(dir); | ||
-} | ||
- | ||
static int parse_branchname_arg(int argc, const char **argv, | ||
int dwim_new_local_branch_ok, | ||
struct branch_info *new, | ||
@@ -1170,14 +1101,14 @@ static int checkout_branch(struct checkout_opts *opts, | ||
die(_("Cannot switch branch to a non-commit '%s'"), | ||
new->name); | ||
- if (new->path && !opts->force_detach && !opts->new_branch) { | ||
+ if (new->path && !opts->force_detach && !opts->new_branch && | ||
+ !opts->ignore_other_worktrees) { | ||
unsigned char sha1[20]; | ||
int flag; | ||
char *head_ref = resolve_refdup("HEAD", 0, sha1, &flag); | ||
if (head_ref && | ||
- (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)) && | ||
- !opts->ignore_other_worktrees) | ||
- check_linked_checkouts(new); | ||
+ (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path))) | ||
+ die_if_checked_out(new->path); | ||
free(head_ref); | ||
} | ||
@@ -1241,8 +1172,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) | ||
argc = parse_options(argc, argv, prefix, options, checkout_usage, | ||
PARSE_OPT_KEEP_DASHDASH); | ||
- opts.new_worktree_mode = getenv("GIT_CHECKOUT_NEW_WORKTREE") != NULL; | ||
- | ||
if (conflict_style) { | ||
opts.merge = 1; /* implied */ | ||
git_xmerge_config("merge.conflictstyle", conflict_style, NULL); | ||
View
30
builtin/clean.c
@@ -10,7 +10,6 @@ | ||
#include "cache.h" | ||
#include "dir.h" | ||
#include "parse-options.h" | ||
-#include "refs.h" | ||
#include "string-list.h" | ||
#include "quote.h" | ||
#include "column.h" | ||
@@ -148,6 +147,31 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset) | ||
return 0; | ||
} | ||
+/* | ||
+ * Return 1 if the given path is the root of a git repository or | ||
+ * submodule else 0. Will not return 1 for bare repositories with the | ||
+ * exception of creating a bare repository in "foo/.git" and calling | ||
+ * is_git_repository("foo"). | ||
+ */ | ||
+static int is_git_repository(struct strbuf *path) | ||
+{ | ||
+ int ret = 0; | ||
+ int gitfile_error; | ||
+ size_t orig_path_len = path->len; | ||
+ assert(orig_path_len != 0); | ||
+ if (path->buf[orig_path_len - 1] != '/') | ||
+ strbuf_addch(path, '/'); | ||
+ strbuf_addstr(path, ".git"); | ||
+ if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf)) | ||
+ ret = 1; | ||
+ if (gitfile_error == READ_GITFILE_ERR_OPEN_FAILED || | ||
+ gitfile_error == READ_GITFILE_ERR_READ_FAILED) | ||
+ ret = 1; /* This could be a real .git file, take the | ||
+ * safe option and avoid cleaning */ | ||
+ strbuf_setlen(path, orig_path_len); | ||
+ return ret; | ||
+} | ||
+ | ||
static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, | ||
int dry_run, int quiet, int *dir_gone) | ||
{ | ||
@@ -155,13 +179,11 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, | ||
struct strbuf quoted = STRBUF_INIT; | ||
struct dirent *e; | ||
int res = 0, ret = 0, gone = 1, original_len = path->len, len; | ||
- unsigned char submodule_head[20]; | ||
struct string_list dels = STRING_LIST_INIT_DUP; | ||
*dir_gone = 1; | ||
- if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && | ||
- !resolve_gitlink_ref(path->buf, "HEAD", submodule_head)) { | ||
+ if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_git_repository(path)) { | ||
if (!quiet) { | ||
quote_path_relative(path->buf, prefix, "ed); | ||
printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir), | ||
View
126
builtin/clone.c
@@ -99,82 +99,140 @@ static const char *argv_submodule[] = { | ||
"submodule", "update", "--init", "--recursive", NULL | ||
}; | ||
-static char *get_repo_path(const char *repo, int *is_bundle) | ||
+static const char *get_repo_path_1(struct strbuf *path, int *is_bundle) | ||
{ | ||
static char *suffix[] = { "/.git", "", ".git/.git", ".git" }; | ||
static char *bundle_suffix[] = { ".bundle", "" }; | ||
+ size_t baselen = path->len; | ||
struct stat st; | ||
int i; | ||
for (i = 0; i < ARRAY_SIZE(suffix); i++) { | ||
- const char *path; | ||
- path = mkpath("%s%s", repo, suffix[i]); | ||
- if (stat(path, &st)) | ||
+ strbuf_setlen(path, baselen); | ||
+ strbuf_addstr(path, suffix[i]); | ||
+ if (stat(path->buf, &st)) | ||
continue; | ||
- if (S_ISDIR(st.st_mode) && is_git_directory(path)) { | ||
+ if (S_ISDIR(st.st_mode) && is_git_directory(path->buf)) { | ||
*is_bundle = 0; | ||
- return xstrdup(absolute_path(path)); | ||
+ return path->buf; | ||
} else if (S_ISREG(st.st_mode) && st.st_size > 8) { | ||
/* Is it a "gitfile"? */ | ||
char signature[8]; | ||
- int len, fd = open(path, O_RDONLY); | ||
+ const char *dst; | ||
+ int len, fd = open(path->buf, O_RDONLY); | ||
if (fd < 0) | ||
continue; | ||
len = read_in_full(fd, signature, 8); | ||
close(fd); | ||
if (len != 8 || strncmp(signature, "gitdir: ", 8)) | ||
continue; | ||
- path = read_gitfile(path); | ||
- if (path) { | ||
+ dst = read_gitfile(path->buf); | ||
+ if (dst) { | ||
*is_bundle = 0; | ||
- return xstrdup(absolute_path(path)); | ||
+ return dst; | ||
} | ||
} | ||
} | ||
for (i = 0; i < ARRAY_SIZE(bundle_suffix); i++) { | ||
- const char *path; | ||
- path = mkpath("%s%s", repo, bundle_suffix[i]); | ||
- if (!stat(path, &st) && S_ISREG(st.st_mode)) { | ||
+ strbuf_setlen(path, baselen); | ||
+ strbuf_addstr(path, bundle_suffix[i]); | ||
+ if (!stat(path->buf, &st) && S_ISREG(st.st_mode)) { | ||
*is_bundle = 1; | ||
- return xstrdup(absolute_path(path)); | ||
+ return path->buf; | ||
} | ||
} | ||
return NULL; | ||
} | ||
+static char *get_repo_path(const char *repo, int *is_bundle) | ||
+{ | ||
+ struct strbuf path = STRBUF_INIT; | ||
+ const char *raw; | ||
+ char *canon; | ||
+ | ||
+ strbuf_addstr(&path, repo); | ||
+ raw = get_repo_path_1(&path, is_bundle); | ||
+ canon = raw ? xstrdup(absolute_path(raw)) : NULL; | ||
+ strbuf_release(&path); | ||
+ return canon; | ||
+} | ||
+ | ||
static char *guess_dir_name(const char *repo, int is_bundle, int is_bare) | ||
{ | ||
- const char *end = repo + strlen(repo), *start; | ||
+ const char *end = repo + strlen(repo), *start, *ptr; | ||
size_t len; | ||
char *dir; | ||
/* | ||
+ * Skip scheme. | ||
+ */ | ||
+ start = strstr(repo, "://"); | ||
+ if (start == NULL) | ||
+ start = repo; | ||
+ else | ||
+ start += 3; | ||
+ | ||
+ /* | ||
+ * Skip authentication data. The stripping does happen | ||
+ * greedily, such that we strip up to the last '@' inside | ||
+ * the host part. | ||
+ */ | ||
+ for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) { | ||
+ if (*ptr == '@') | ||
+ start = ptr + 1; | ||
+ } | ||
+ | ||
+ /* | ||
* Strip trailing spaces, slashes and /.git | ||
*/ | ||
- while (repo < end && (is_dir_sep(end[-1]) || isspace(end[-1]))) | ||
+ while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1]))) | ||
end--; | ||
- if (end - repo > 5 && is_dir_sep(end[-5]) && | ||
+ if (end - start > 5 && is_dir_sep(end[-5]) && | ||
!strncmp(end - 4, ".git", 4)) { | ||
end -= 5; | ||
- while (repo < end && is_dir_sep(end[-1])) | ||
+ while (start < end && is_dir_sep(end[-1])) | ||
end--; | ||
} | ||
/* | ||
- * 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. | ||
+ * Strip trailing port number if we've got only a | ||
+ * hostname (that is, there is no dir separator but a | ||
+ * colon). This check is required such that we do not | ||
+ * strip URI's like '/foo/bar:2222.git', which should | ||
+ * result in a dir '2222' being guessed due to backwards | ||
+ * compatibility. | ||
+ */ | ||
+ if (memchr(start, '/', end - start) == NULL | ||
+ && memchr(start, ':', end - start) != NULL) { | ||
+ ptr = end; | ||
+ while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':') | ||
+ ptr--; | ||
+ if (start < ptr && ptr[-1] == ':') | ||
+ end = ptr - 1; | ||
+ } | ||
+ | ||
+ /* | ||
+ * Find last component. To remain backwards compatible we | ||
+ * also regard colons as path separators, such that | ||
+ * cloning a repository 'foo:bar.git' would result in a | ||
+ * directory 'bar' being guessed. | ||
*/ | ||
- start = end; | ||
- while (repo < start && !is_dir_sep(start[-1]) && start[-1] != ':') | ||
- start--; | ||
+ ptr = end; | ||
+ while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':') | ||
+ ptr--; | ||
+ start = ptr; | ||
/* | ||
* Strip .{bundle,git}. | ||
*/ | ||
- strip_suffix(start, is_bundle ? ".bundle" : ".git" , &len); | ||
+ len = end - start; | ||
+ strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git"); | ||
+ | ||
+ if (!len || (len == 1 && *start == '/')) | ||
+ die("No directory name could be guessed.\n" | ||
+ "Please specify a directory on the command line"); | ||
if (is_bare) | ||
dir = xstrfmt("%.*s.git", (int)len, start); | ||
@@ -484,16 +542,26 @@ static void write_remote_refs(const struct ref *local_refs) | ||
{ | ||
const struct ref *r; | ||
- lock_packed_refs(LOCK_DIE_ON_ERROR); | ||
+ struct ref_transaction *t; | ||
+ struct strbuf err = STRBUF_INIT; | ||
+ | ||
+ t = ref_transaction_begin(&err); | ||
+ if (!t) | ||
+ die("%s", err.buf); | ||
for (r = local_refs; r; r = r->next) { | ||
if (!r->peer_ref) | ||
continue; | ||
- add_packed_ref(r->peer_ref->name, r->old_sha1); | ||
+ if (ref_transaction_create(t, r->peer_ref->name, r->old_sha1, | ||
+ 0, NULL, &err)) | ||
+ die("%s", err.buf); | ||
} | ||
- if (commit_packed_refs()) | ||
- die_errno("unable to overwrite old ref-pack file"); | ||
+ if (initial_ref_transaction_commit(t, &err)) | ||
+ die("%s", err.buf); | ||
+ | ||
+ strbuf_release(&err); | ||
+ ref_transaction_free(t); | ||
} | ||
static void write_followtags(const struct ref *refs, const char *msg) | ||
View
55
builtin/commit.c
@@ -166,9 +166,9 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset) | ||
static void determine_whence(struct wt_status *s) | ||
{ | ||
- if (file_exists(git_path("MERGE_HEAD"))) | ||
+ if (file_exists(git_path_merge_head())) | ||
whence = FROM_MERGE; | ||
- else if (file_exists(git_path("CHERRY_PICK_HEAD"))) { | ||
+ else if (file_exists(git_path_cherry_pick_head())) { | ||
whence = FROM_CHERRY_PICK; | ||
if (file_exists(git_path(SEQ_DIR))) | ||
sequencer_in_use = 1; | ||
@@ -324,6 +324,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix | ||
struct string_list partial; | ||
struct pathspec pathspec; | ||
int refresh_flags = REFRESH_QUIET; | ||
+ const char *ret; | ||
if (is_status) | ||
refresh_flags |= REFRESH_UNMERGED; | ||
@@ -344,7 +345,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix | ||
die(_("unable to create temporary index")); | ||
old_index_env = getenv(INDEX_ENVIRONMENT); | ||
- setenv(INDEX_ENVIRONMENT, index_lock.filename.buf, 1); | ||
+ setenv(INDEX_ENVIRONMENT, get_lock_file_path(&index_lock), 1); | ||
if (interactive_add(argc, argv, prefix, patch_interactive) != 0) | ||
die(_("interactive add failed")); | ||
@@ -355,7 +356,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix | ||
unsetenv(INDEX_ENVIRONMENT); | ||
discard_cache(); | ||
- read_cache_from(index_lock.filename.buf); | ||
+ read_cache_from(get_lock_file_path(&index_lock)); | ||
if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) { | ||
if (reopen_lock_file(&index_lock) < 0) | ||
die(_("unable to write index file")); | ||
@@ -365,7 +366,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix | ||
warning(_("Failed to update main cache tree")); | ||
commit_style = COMMIT_NORMAL; | ||
- return index_lock.filename.buf; | ||
+ return get_lock_file_path(&index_lock); | ||
} | ||
/* | ||
@@ -388,7 +389,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix | ||
if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK)) | ||
die(_("unable to write new_index file")); | ||
commit_style = COMMIT_NORMAL; | ||
- return index_lock.filename.buf; | ||
+ return get_lock_file_path(&index_lock); | ||
} | ||
/* | ||
@@ -404,10 +405,8 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix | ||
hold_locked_index(&index_lock, 1); | ||
refresh_cache_or_die(refresh_flags); | ||
if (active_cache_changed | ||
- || !cache_tree_fully_valid(active_cache_tree)) { | ||
+ || !cache_tree_fully_valid(active_cache_tree)) | ||
update_main_cache_tree(WRITE_TREE_SILENT); | ||
- active_cache_changed = 1; | ||
- } | ||
if (active_cache_changed) { | ||
if (write_locked_index(&the_index, &index_lock, | ||
COMMIT_LOCK)) | ||
@@ -475,9 +474,9 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix | ||
die(_("unable to write temporary index file")); | ||
discard_cache(); | ||
- read_cache_from(false_lock.filename.buf); | ||
- | ||
- return false_lock.filename.buf; | ||
+ ret = get_lock_file_path(&false_lock); | ||
+ read_cache_from(ret); | ||
+ return ret; | ||
} | ||
static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn, | ||
@@ -725,12 +724,12 @@ static int prepare_to_commit(const char *index_file, const char *prefix, | ||
format_commit_message(commit, "fixup! %s\n\n", | ||
&sb, &ctx); | ||
hook_arg1 = "message"; | ||
- } else if (!stat(git_path("MERGE_MSG"), &statbuf)) { | ||
- if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0) | ||
+ } else if (!stat(git_path_merge_msg(), &statbuf)) { | ||
+ if (strbuf_read_file(&sb, git_path_merge_msg(), 0) < 0) | ||
die_errno(_("could not read MERGE_MSG")); | ||
hook_arg1 = "merge"; | ||
- } else if (!stat(git_path("SQUASH_MSG"), &statbuf)) { | ||
- if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0) | ||
+ } else if (!stat(git_path_squash_msg(), &statbuf)) { | ||
+ if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0) | ||
die_errno(_("could not read SQUASH_MSG")); | ||
hook_arg1 = "squash"; | ||
} else if (template_file) { | ||
@@ -856,7 +855,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, | ||
_("%s" | ||
"Date: %s"), | ||
ident_shown++ ? "" : "\n", | ||
- show_ident_date(&ai, DATE_NORMAL)); | ||
+ show_ident_date(&ai, DATE_MODE(NORMAL))); | ||
if (!committer_ident_sufficiently_given()) | ||
status_printf_ln(s, GIT_COLOR_NORMAL, | ||
@@ -1046,7 +1045,7 @@ static const char *find_author_by_nickname(const char *name) | ||
commit = get_revision(&revs); | ||
if (commit) { | ||
struct pretty_print_context ctx = {0}; | ||
- ctx.date_mode = DATE_NORMAL; | ||
+ ctx.date_mode.type = DATE_NORMAL; | ||
strbuf_release(&buf); | ||
format_commit_message(commit, "%aN <%aE>", &buf, &ctx); | ||
clear_mailmap(&mailmap); | ||
@@ -1684,10 +1683,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix) | ||
if (!reflog_msg) | ||
reflog_msg = "commit (merge)"; | ||
pptr = &commit_list_insert(current_head, pptr)->next; | ||
- fp = fopen(git_path("MERGE_HEAD"), "r"); | ||
+ fp = fopen(git_path_merge_head(), "r"); | ||
if (fp == NULL) | ||
die_errno(_("could not open '%s' for reading"), | ||
- git_path("MERGE_HEAD")); | ||
+ git_path_merge_head()); | ||
while (strbuf_getline(&m, fp, '\n') != EOF) { | ||
struct commit *parent; | ||
@@ -1698,8 +1697,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) | ||
} | ||
fclose(fp); | ||
strbuf_release(&m); | ||
- if (!stat(git_path("MERGE_MODE"), &statbuf)) { | ||
- if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0) | ||
+ if (!stat(git_path_merge_mode(), &statbuf)) { | ||
+ if (strbuf_read_file(&sb, git_path_merge_mode(), 0) < 0) | ||
die_errno(_("could not read MERGE_MODE")); | ||
if (!strcmp(sb.buf, "no-ff")) | ||
allow_fast_forward = 0; | ||
@@ -1775,12 +1774,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix) | ||
} | ||
ref_transaction_free(transaction); | ||
- unlink(git_path("CHERRY_PICK_HEAD")); | ||
- unlink(git_path("REVERT_HEAD")); | ||
- unlink(git_path("MERGE_HEAD")); | ||
- unlink(git_path("MERGE_MSG")); | ||
- unlink(git_path("MERGE_MODE")); | ||
- unlink(git_path("SQUASH_MSG")); | ||
+ unlink(git_path_cherry_pick_head()); | ||
+ unlink(git_path_revert_head()); | ||
+ unlink(git_path_merge_head()); | ||
+ unlink(git_path_merge_msg()); | ||
+ unlink(git_path_merge_mode()); | ||
+ unlink(git_path_squash_msg()); | ||
if (commit_index_files()) | ||
die (_("Repository has been updated, but unable to write\n" | ||
View
86
builtin/config.c
@@ -13,6 +13,7 @@ static char *key; | ||
static regex_t *key_regexp; | ||
static regex_t *regexp; | ||
static int show_keys; | ||
+static int omit_values; | ||
static int use_key_regexp; | ||
static int do_all; | ||
static int do_not_match; | ||
@@ -78,6 +79,7 @@ static struct option builtin_config_options[] = { | ||
OPT_BIT(0, "path", &types, N_("value is a path (file or directory name)"), TYPE_PATH), | ||
OPT_GROUP(N_("Other")), | ||
OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")), | ||
+ OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")), | ||
OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")), | ||
OPT_END(), | ||
}; | ||
@@ -91,7 +93,7 @@ static void check_argc(int argc, int min, int max) { | ||
static int show_all_config(const char *key_, const char *value_, void *cb) | ||
{ | ||
- if (value_) | ||
+ if (!omit_values && value_) | ||
printf("%s%c%s%c", key_, delim, value_, term); | ||
else | ||
printf("%s%c", key_, term); | ||
@@ -106,48 +108,40 @@ struct strbuf_list { | ||
static int format_config(struct strbuf *buf, const char *key_, const char *value_) | ||
{ | ||
- int must_free_vptr = 0; | ||
- int must_print_delim = 0; | ||
- char value[256]; | ||
- const char *vptr = value; | ||
- | ||
- strbuf_init(buf, 0); | ||
- | ||
- if (show_keys) { | ||
+ if (show_keys) | ||
strbuf_addstr(buf, key_); | ||
- must_print_delim = 1; | ||
- } | ||
- if (types == TYPE_INT) | ||
- sprintf(value, "%"PRId64, | ||
- git_config_int64(key_, value_ ? value_ : "")); | ||
- else if (types == TYPE_BOOL) | ||
- vptr = git_config_bool(key_, value_) ? "true" : "false"; | ||
- else if (types == TYPE_BOOL_OR_INT) { | ||
- int is_bool, v; | ||
- v = git_config_bool_or_int(key_, value_, &is_bool); | ||
- if (is_bool) | ||
- vptr = v ? "true" : "false"; | ||
- else | ||
- sprintf(value, "%d", v); | ||
- } else if (types == TYPE_PATH) { | ||
- if (git_config_pathname(&vptr, key_, value_) < 0) | ||
- return -1; | ||
- must_free_vptr = 1; | ||
- } else if (value_) { | ||
- vptr = value_; | ||
- } else { | ||
- /* Just show the key name */ | ||
- vptr = ""; | ||
- must_print_delim = 0; | ||
- } | ||
+ if (!omit_values) { | ||
+ if (show_keys) | ||
+ strbuf_addch(buf, key_delim); | ||
- if (must_print_delim) | ||
- strbuf_addch(buf, key_delim); | ||
- strbuf_addstr(buf, vptr); | ||
+ if (types == TYPE_INT) | ||
+ strbuf_addf(buf, "%"PRId64, | ||
+ git_config_int64(key_, value_ ? value_ : "")); | ||
+ else if (types == TYPE_BOOL) | ||
+ strbuf_addstr(buf, git_config_bool(key_, value_) ? | ||
+ "true" : "false"); | ||
+ else if (types == TYPE_BOOL_OR_INT) { | ||
+ int is_bool, v; | ||
+ v = git_config_bool_or_int(key_, value_, &is_bool); | ||
+ if (is_bool) | ||
+ strbuf_addstr(buf, v ? "true" : "false"); | ||
+ else | ||
+ strbuf_addf(buf, "%d", v); | ||
+ } else if (types == TYPE_PATH) { | ||
+ const char *v; | ||
+ if (git_config_pathname(&v, key_, value_) < 0) | ||
+ return -1; | ||
+ strbuf_addstr(buf, v); | ||
+ free((char *)v); | ||
+ } else if (value_) { | ||
+ strbuf_addstr(buf, value_); | ||
+ } else { | ||
+ /* Just show the key name; back out delimiter */ | ||
+ if (show_keys) | ||
+ strbuf_setlen(buf, buf->len - 1); | ||
+ } | ||
+ } | ||
strbuf_addch(buf, term); | ||
- | ||
- if (must_free_vptr) | ||
- free((char *)vptr); | ||
return 0; | ||
} | ||
@@ -164,6 +158,7 @@ static int collect_config(const char *key_, const char *value_, void *cb) | ||
return 0; | ||
ALLOC_GROW(values->items, values->nr + 1, values->alloc); | ||
+ strbuf_init(&values->items[values->nr], 0); | ||
return format_config(&values->items[values->nr++], key_, value_); | ||
} | ||
@@ -430,14 +425,11 @@ static int get_urlmatch(const char *var, const char *url) | ||
for_each_string_list_item(item, &values) { | ||
struct urlmatch_current_candidate_value *matched = item->util; | ||
- struct strbuf key = STRBUF_INIT; | ||
struct strbuf buf = STRBUF_INIT; | ||
- strbuf_addstr(&key, item->string); | ||
- format_config(&buf, key.buf, | ||
+ format_config(&buf, item->string, | ||
matched->value_is_null ? NULL : matched->value.buf); | ||
fwrite(buf.buf, 1, buf.len, stdout); | ||
- strbuf_release(&key); | ||
strbuf_release(&buf); | ||
strbuf_release(&matched->value); | ||
@@ -549,7 +541,11 @@ int cmd_config(int argc, const char **argv, const char *prefix) | ||
default: | ||
usage_with_options(builtin_config_usage, builtin_config_options); | ||
} | ||
- | ||
+ if (omit_values && | ||
+ !(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) { | ||
+ error("--name-only is only applicable to --list or --get-regexp"); | ||
+ usage_with_options(builtin_config_usage, builtin_config_options); | ||
+ } | ||
if (actions == ACTION_LIST) { | ||
check_argc(argc, 0, 0); | ||
if (git_config_with_options(show_all_config, NULL, | ||
View
8
builtin/describe.c
@@ -443,10 +443,10 @@ int cmd_describe(int argc, const char **argv, const char *prefix) | ||
if (pattern) | ||
argv_array_pushf(&args, "--refs=refs/tags/%s", pattern); | ||
} | ||
- while (*argv) { | ||
- argv_array_push(&args, *argv); | ||
- argv++; | ||
- } | ||
+ if (argc) | ||
+ argv_array_pushv(&args, argv); | ||
+ else | ||
+ argv_array_push(&args, "HEAD"); | ||
return cmd_name_rev(args.argc, args.argv, prefix); | ||
} | ||
View
1
builtin/fast-export.c
@@ -5,6 +5,7 @@ | ||
*/ | ||
#include "builtin.h" | ||
#include "cache.h" | ||
+#include "refs.h" | ||
#include "commit.h" | ||
#include "object.h" | ||
#include "tag.h" | ||
View
44
builtin/fetch.c
@@ -11,6 +11,7 @@ | ||
#include "run-command.h" | ||
#include "parse-options.h" | ||
#include "sigchain.h" | ||
+#include "submodule-config.h" | ||
#include "submodule.h" | ||
#include "connected.h" | ||
#include "argv-array.h" | ||
@@ -591,7 +592,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, | ||
const char *what, *kind; | ||
struct ref *rm; | ||
char *url; | ||
- const char *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD"); | ||
+ const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(); | ||
int want_status; | ||
fp = fopen(filename, "a"); | ||
@@ -790,20 +791,29 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, | ||
if (4 < i && !strncmp(".git", url + i - 3, 4)) | ||
url_len = i - 3; | ||
- for (ref = stale_refs; ref; ref = ref->next) { | ||
- if (!dry_run) | ||
- result |= delete_ref(ref->name, NULL, 0); | ||
- if (verbosity >= 0 && !shown_url) { | ||
- fprintf(stderr, _("From %.*s\n"), url_len, url); | ||
- shown_url = 1; | ||
- } | ||
- if (verbosity >= 0) { | ||
+ if (!dry_run) { | ||
+ struct string_list refnames = STRING_LIST_INIT_NODUP; | ||
+ | ||
+ for (ref = stale_refs; ref; ref = ref->next) | ||
+ string_list_append(&refnames, ref->name); | ||
+ | ||
+ result = delete_refs(&refnames); | ||
+ string_list_clear(&refnames, 0); | ||
+ } | ||
+ | ||
+ if (verbosity >= 0) { | ||
+ for (ref = stale_refs; ref; ref = ref->next) { | ||
+ if (!shown_url) { | ||
+ fprintf(stderr, _("From %.*s\n"), url_len, url); | ||
+ shown_url = 1; | ||
+ } | ||
fprintf(stderr, " x %-*s %-*s -> %s\n", | ||
TRANSPORT_SUMMARY(_("[deleted]")), | ||
REFCOL_WIDTH, _("(none)"), prettify_refname(ref->name)); | ||
warn_dangling_symref(stderr, dangling_msg, ref->name); | ||
} | ||
} | ||
+ | ||
free(url); | ||
free_refs(stale_refs); | ||
return result; | ||
@@ -825,7 +835,7 @@ static void check_not_current_branch(struct ref *ref_map) | ||
static int truncate_fetch_head(void) | ||
{ | ||
- const char *filename = git_path("FETCH_HEAD"); | ||
+ const char *filename = git_path_fetch_head(); | ||
FILE *fp = fopen(filename, "w"); | ||
if (!fp) | ||
@@ -979,17 +989,15 @@ static int get_remote_group(const char *key, const char *value, void *priv) | ||
{ | ||
struct remote_group_data *g = priv; | ||
- if (starts_with(key, "remotes.") && | ||
- !strcmp(key + 8, g->name)) { | ||
+ if (skip_prefix(key, "remotes.", &key) && !strcmp(key, g->name)) { | ||
/* split list by white space */ | ||
- int space = strcspn(value, " \t\n"); | ||
while (*value) { | ||
- if (space > 1) { | ||
+ size_t wordlen = strcspn(value, " \t\n"); | ||
+ | ||
+ if (wordlen >= 1) | ||
string_list_append(g->list, | ||
- xstrndup(value, space)); | ||
- } | ||
- value += space + (value[space] != '\0'); | ||
- space = strcspn(value, " \t\n"); | ||
+ xstrndup(value, wordlen)); | ||
+ value += wordlen + (value[wordlen] != '\0'); | ||
} | ||
} | ||
View
1
builtin/fmt-merge-msg.c
@@ -1,5 +1,6 @@ | ||
#include "builtin.h" | ||
#include "cache.h" | ||
+#include "refs.h" | ||
#include "commit.h" | ||
#include "diff.h" | ||
#include "revision.h" | ||
View
1,113
builtin/for-each-ref.c
@@ -2,1082 +2,8 @@ | ||
#include "cache.h" | ||
#include "refs.h" | ||
#include "object.h" | ||
-#include "tag.h" | ||
-#include "commit.h" | ||
-#include "tree.h" | ||
-#include "blob.h" | ||
-#include "quote.h" | ||
#include "parse-options.h" | ||
-#include "remote.h" | ||
-#include "color.h" | ||
- | ||
-/* Quoting styles */ | ||
-#define QUOTE_NONE 0 | ||
-#define QUOTE_SHELL 1 | ||
-#define QUOTE_PERL 2 | ||
-#define QUOTE_PYTHON 4 | ||
-#define QUOTE_TCL 8 | ||
- | ||
-typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type; | ||
- | ||
-struct atom_value { | ||
- const char *s; | ||
- unsigned long ul; /* used for sorting when not FIELD_STR */ | ||
-}; | ||
- | ||
-struct ref_sort { | ||
- struct ref_sort *next; | ||
- int atom; /* index into used_atom array */ | ||
- unsigned reverse : 1; | ||
-}; | ||
- | ||
-struct refinfo { | ||
- char *refname; | ||
- unsigned char objectname[20]; | ||
- int flag; | ||
- const char *symref; | ||
- struct atom_value *value; | ||
-}; | ||
- | ||
-static struct { | ||
- const char *name; | ||
- cmp_type cmp_type; | ||
-} valid_atom[] = { | ||
- { "refname" }, | ||
- { "objecttype" }, | ||
- { "objectsize", FIELD_ULONG }, | ||
- { "objectname" }, | ||
- { "tree" }, | ||
- { "parent" }, | ||
- { "numparent", FIELD_ULONG }, | ||
- { "object" }, | ||
- { "type" }, | ||
- { "tag" }, | ||
- { "author" }, | ||
- { "authorname" }, | ||
- { "authoremail" }, | ||
- { "authordate", FIELD_TIME }, | ||
- { "committer" }, | ||
- { "committername" }, | ||
- { "committeremail" }, | ||
- { "committerdate", FIELD_TIME }, | ||
- { "tagger" }, | ||
- { "taggername" }, | ||
- { "taggeremail" }, | ||
- { "taggerdate", FIELD_TIME }, | ||
- { "creator" }, | ||
- { "creatordate", FIELD_TIME }, | ||
- { "subject" }, | ||
- { "body" }, | ||
- { "contents" }, | ||
- { "contents:subject" }, | ||
- { "contents:body" }, | ||
- { "contents:signature" }, | ||
- { "upstream" }, | ||
- { "push" }, | ||
- { "symref" }, | ||
- { "flag" }, | ||
- { "HEAD" }, | ||
- { "color" }, | ||
-}; | ||
- | ||
-/* | ||
- * An atom is a valid field atom listed above, possibly prefixed with | ||
- * a "*" to denote deref_tag(). | ||
- * | ||
- * We parse given format string and sort specifiers, and make a list | ||
- * of properties that we need to extract out of objects. refinfo | ||
- * structure will hold an array of values extracted that can be | ||
- * indexed with the "atom number", which is an index into this | ||
- * array. | ||
- */ | ||
-static const char **used_atom; | ||
-static cmp_type *used_atom_type; | ||
-static int used_atom_cnt, need_tagged, need_symref; | ||
-static int need_color_reset_at_eol; | ||
- | ||
-/* | ||
- * Used to parse format string and sort specifiers | ||
- */ | ||
-static int parse_atom(const char *atom, const char *ep) | ||
-{ | ||
- const char *sp; | ||
- int i, at; | ||
- | ||
- sp = atom; | ||
- if (*sp == '*' && sp < ep) | ||
- sp++; /* deref */ | ||
- if (ep <= sp) | ||
- die("malformed field name: %.*s", (int)(ep-atom), atom); | ||
- | ||
- /* Do we have the atom already used elsewhere? */ | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- int len = strlen(used_atom[i]); | ||
- if (len == ep - atom && !memcmp(used_atom[i], atom, len)) | ||
- return i; | ||
- } | ||
- | ||
- /* Is the atom a valid one? */ | ||
- for (i = 0; i < ARRAY_SIZE(valid_atom); i++) { | ||
- int len = strlen(valid_atom[i].name); | ||
- /* | ||
- * If the atom name has a colon, strip it and everything after | ||
- * it off - it specifies the format for this entry, and | ||
- * shouldn't be used for checking against the valid_atom | ||
- * table. | ||
- */ | ||
- const char *formatp = strchr(sp, ':'); | ||
- if (!formatp || ep < formatp) | ||
- formatp = ep; | ||
- if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len)) | ||
- break; | ||
- } | ||
- | ||
- if (ARRAY_SIZE(valid_atom) <= i) | ||
- die("unknown field name: %.*s", (int)(ep-atom), atom); | ||
- | ||
- /* Add it in, including the deref prefix */ | ||
- at = used_atom_cnt; | ||
- used_atom_cnt++; | ||
- REALLOC_ARRAY(used_atom, used_atom_cnt); | ||
- REALLOC_ARRAY(used_atom_type, used_atom_cnt); | ||
- used_atom[at] = xmemdupz(atom, ep - atom); | ||
- used_atom_type[at] = valid_atom[i].cmp_type; | ||
- if (*atom == '*') | ||
- need_tagged = 1; | ||
- if (!strcmp(used_atom[at], "symref")) | ||
- need_symref = 1; | ||
- return at; | ||
-} | ||
- | ||
-/* | ||
- * In a format string, find the next occurrence of %(atom). | ||
- */ | ||
-static const char *find_next(const char *cp) | ||
-{ | ||
- while (*cp) { | ||
- if (*cp == '%') { | ||
- /* | ||
- * %( is the start of an atom; | ||
- * %% is a quoted per-cent. | ||
- */ | ||
- if (cp[1] == '(') | ||
- return cp; | ||
- else if (cp[1] == '%') | ||
- cp++; /* skip over two % */ | ||
- /* otherwise this is a singleton, literal % */ | ||
- } | ||
- cp++; | ||
- } | ||
- return NULL; | ||
-} | ||
- | ||
-/* | ||
- * Make sure the format string is well formed, and parse out | ||
- * the used atoms. | ||
- */ | ||
-static int verify_format(const char *format) | ||
-{ | ||
- const char *cp, *sp; | ||
- | ||
- need_color_reset_at_eol = 0; | ||
- for (cp = format; *cp && (sp = find_next(cp)); ) { | ||
- const char *color, *ep = strchr(sp, ')'); | ||
- int at; | ||
- | ||
- if (!ep) | ||
- return error("malformed format string %s", sp); | ||
- /* sp points at "%(" and ep points at the closing ")" */ | ||
- at = parse_atom(sp + 2, ep); | ||
- cp = ep + 1; | ||
- | ||
- if (skip_prefix(used_atom[at], "color:", &color)) | ||
- need_color_reset_at_eol = !!strcmp(color, "reset"); | ||
- } | ||
- return 0; | ||
-} | ||
- | ||
-/* | ||
- * Given an object name, read the object data and size, and return a | ||
- * "struct object". If the object data we are returning is also borrowed | ||
- * by the "struct object" representation, set *eaten as well---it is a | ||
- * signal from parse_object_buffer to us not to free the buffer. | ||
- */ | ||
-static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten) | ||
-{ | ||
- enum object_type type; | ||
- void *buf = read_sha1_file(sha1, &type, sz); | ||
- | ||
- if (buf) | ||
- *obj = parse_object_buffer(sha1, type, *sz, buf, eaten); | ||
- else | ||
- *obj = NULL; | ||
- return buf; | ||
-} | ||
- | ||
-static int grab_objectname(const char *name, const unsigned char *sha1, | ||
- struct atom_value *v) | ||
-{ | ||
- if (!strcmp(name, "objectname")) { | ||
- char *s = xmalloc(41); | ||
- strcpy(s, sha1_to_hex(sha1)); | ||
- v->s = s; | ||
- return 1; | ||
- } | ||
- if (!strcmp(name, "objectname:short")) { | ||
- v->s = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | ||
- return 1; | ||
- } | ||
- return 0; | ||
-} | ||
- | ||
-/* See grab_values */ | ||
-static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz) | ||
-{ | ||
- int i; | ||
- | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- const char *name = used_atom[i]; | ||
- struct atom_value *v = &val[i]; | ||
- if (!!deref != (*name == '*')) | ||
- continue; | ||
- if (deref) | ||
- name++; | ||
- if (!strcmp(name, "objecttype")) | ||
- v->s = typename(obj->type); | ||
- else if (!strcmp(name, "objectsize")) { | ||
- char *s = xmalloc(40); | ||
- sprintf(s, "%lu", sz); | ||
- v->ul = sz; | ||
- v->s = s; | ||
- } | ||
- else if (deref) | ||
- grab_objectname(name, obj->sha1, v); | ||
- } | ||
-} | ||
- | ||
-/* See grab_values */ | ||
-static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz) | ||
-{ | ||
- int i; | ||
- struct tag *tag = (struct tag *) obj; | ||
- | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- const char *name = used_atom[i]; | ||
- struct atom_value *v = &val[i]; | ||
- if (!!deref != (*name == '*')) | ||
- continue; | ||
- if (deref) | ||
- name++; | ||
- if (!strcmp(name, "tag")) | ||
- v->s = tag->tag; | ||
- else if (!strcmp(name, "type") && tag->tagged) | ||
- v->s = typename(tag->tagged->type); | ||
- else if (!strcmp(name, "object") && tag->tagged) { | ||
- char *s = xmalloc(41); | ||
- strcpy(s, sha1_to_hex(tag->tagged->sha1)); | ||
- v->s = s; | ||
- } | ||
- } | ||
-} | ||
- | ||
-/* See grab_values */ | ||
-static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz) | ||
-{ | ||
- int i; | ||
- struct commit *commit = (struct commit *) obj; | ||
- | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- const char *name = used_atom[i]; | ||
- struct atom_value *v = &val[i]; | ||
- if (!!deref != (*name == '*')) | ||
- continue; | ||
- if (deref) | ||
- name++; | ||
- if (!strcmp(name, "tree")) { | ||
- char *s = xmalloc(41); | ||
- strcpy(s, sha1_to_hex(commit->tree->object.sha1)); | ||
- v->s = s; | ||
- } | ||
- if (!strcmp(name, "numparent")) { | ||
- char *s = xmalloc(40); | ||
- v->ul = commit_list_count(commit->parents); | ||
- sprintf(s, "%lu", v->ul); | ||
- v->s = s; | ||
- } | ||
- else if (!strcmp(name, "parent")) { | ||
- int num = commit_list_count(commit->parents); | ||
- int i; | ||
- struct commit_list *parents; | ||
- char *s = xmalloc(41 * num + 1); | ||
- v->s = s; | ||
- for (i = 0, parents = commit->parents; | ||
- parents; | ||
- parents = parents->next, i = i + 41) { | ||
- struct commit *parent = parents->item; | ||
- strcpy(s+i, sha1_to_hex(parent->object.sha1)); | ||
- if (parents->next) | ||
- s[i+40] = ' '; | ||
- } | ||
- if (!i) | ||
- *s = '\0'; | ||
- } | ||
- } | ||
-} | ||
- | ||
-static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz) | ||
-{ | ||
- const char *eol; | ||
- while (*buf) { | ||
- if (!strncmp(buf, who, wholen) && | ||
- buf[wholen] == ' ') | ||
- return buf + wholen + 1; | ||
- eol = strchr(buf, '\n'); | ||
- if (!eol) | ||
- return ""; | ||
- eol++; | ||
- if (*eol == '\n') | ||
- return ""; /* end of header */ | ||
- buf = eol; | ||
- } | ||
- return ""; | ||
-} | ||
- | ||
-static const char *copy_line(const char *buf) | ||
-{ | ||
- const char *eol = strchrnul(buf, '\n'); | ||
- return xmemdupz(buf, eol - buf); | ||
-} | ||
- | ||
-static const char *copy_name(const char *buf) | ||
-{ | ||
- const char *cp; | ||
- for (cp = buf; *cp && *cp != '\n'; cp++) { | ||
- if (!strncmp(cp, " <", 2)) | ||
- return xmemdupz(buf, cp - buf); | ||
- } | ||
- return ""; | ||
-} | ||
- | ||
-static const char *copy_email(const char *buf) | ||
-{ | ||
- const char *email = strchr(buf, '<'); | ||
- const char *eoemail; | ||
- if (!email) | ||
- return ""; | ||
- eoemail = strchr(email, '>'); | ||
- if (!eoemail) | ||
- return ""; | ||
- return xmemdupz(email, eoemail + 1 - email); | ||
-} | ||
- | ||
-static char *copy_subject(const char *buf, unsigned long len) | ||
-{ | ||
- char *r = xmemdupz(buf, len); | ||
- int i; | ||
- | ||
- for (i = 0; i < len; i++) | ||
- if (r[i] == '\n') | ||
- r[i] = ' '; | ||
- | ||
- return r; | ||
-} | ||
- | ||
-static void grab_date(const char *buf, struct atom_value *v, const char *atomname) | ||
-{ | ||
- const char *eoemail = strstr(buf, "> "); | ||
- char *zone; | ||
- unsigned long timestamp; | ||
- long tz; | ||
- enum date_mode date_mode = DATE_NORMAL; | ||
- const char *formatp; | ||
- | ||
- /* | ||
- * We got here because atomname ends in "date" or "date<something>"; | ||
- * it's not possible that <something> is not ":<format>" because | ||
- * parse_atom() wouldn't have allowed it, so we can assume that no | ||
- * ":" means no format is specified, and use the default. | ||
- */ | ||
- formatp = strchr(atomname, ':'); | ||
- if (formatp != NULL) { | ||
- formatp++; | ||
- date_mode = parse_date_format(formatp); | ||
- } | ||
- | ||
- if (!eoemail) | ||
- goto bad; | ||
- timestamp = strtoul(eoemail + 2, &zone, 10); | ||
- if (timestamp == ULONG_MAX) | ||
- goto bad; | ||
- tz = strtol(zone, NULL, 10); | ||
- if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE) | ||
- goto bad; | ||
- v->s = xstrdup(show_date(timestamp, tz, date_mode)); | ||
- v->ul = timestamp; | ||
- return; | ||
- bad: | ||
- v->s = ""; | ||
- v->ul = 0; | ||
-} | ||
- | ||
-/* See grab_values */ | ||
-static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz) | ||
-{ | ||
- int i; | ||
- int wholen = strlen(who); | ||
- const char *wholine = NULL; | ||
- | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- const char *name = used_atom[i]; | ||
- struct atom_value *v = &val[i]; | ||
- if (!!deref != (*name == '*')) | ||
- continue; | ||
- if (deref) | ||
- name++; | ||
- if (strncmp(who, name, wholen)) | ||
- continue; | ||
- if (name[wholen] != 0 && | ||
- strcmp(name + wholen, "name") && | ||
- strcmp(name + wholen, "email") && | ||
- !starts_with(name + wholen, "date")) | ||
- continue; | ||
- if (!wholine) | ||
- wholine = find_wholine(who, wholen, buf, sz); | ||
- if (!wholine) | ||
- return; /* no point looking for it */ | ||
- if (name[wholen] == 0) | ||
- v->s = copy_line(wholine); | ||
- else if (!strcmp(name + wholen, "name")) | ||
- v->s = copy_name(wholine); | ||
- else if (!strcmp(name + wholen, "email")) | ||
- v->s = copy_email(wholine); | ||
- else if (starts_with(name + wholen, "date")) | ||
- grab_date(wholine, v, name); | ||
- } | ||
- | ||
- /* | ||
- * For a tag or a commit object, if "creator" or "creatordate" is | ||
- * requested, do something special. | ||
- */ | ||
- if (strcmp(who, "tagger") && strcmp(who, "committer")) | ||
- return; /* "author" for commit object is not wanted */ | ||
- if (!wholine) | ||
- wholine = find_wholine(who, wholen, buf, sz); | ||
- if (!wholine) | ||
- return; | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- const char *name = used_atom[i]; | ||
- struct atom_value *v = &val[i]; | ||
- if (!!deref != (*name == '*')) | ||
- continue; | ||
- if (deref) | ||
- name++; | ||
- | ||
- if (starts_with(name, "creatordate")) | ||
- grab_date(wholine, v, name); | ||
- else if (!strcmp(name, "creator")) | ||
- v->s = copy_line(wholine); | ||
- } | ||
-} | ||
- | ||
-static void find_subpos(const char *buf, unsigned long sz, | ||
- const char **sub, unsigned long *sublen, | ||
- const char **body, unsigned long *bodylen, | ||
- unsigned long *nonsiglen, | ||
- const char **sig, unsigned long *siglen) | ||
-{ | ||
- const char *eol; | ||
- /* skip past header until we hit empty line */ | ||
- while (*buf && *buf != '\n') { | ||
- eol = strchrnul(buf, '\n'); | ||
- if (*eol) | ||
- eol++; | ||
- buf = eol; | ||
- } | ||
- /* skip any empty lines */ | ||
- while (*buf == '\n') | ||
- buf++; | ||
- | ||
- /* parse signature first; we might not even have a subject line */ | ||
- *sig = buf + parse_signature(buf, strlen(buf)); | ||
- *siglen = strlen(*sig); | ||
- | ||
- /* subject is first non-empty line */ | ||
- *sub = buf; | ||
- /* subject goes to first empty line */ | ||
- while (buf < *sig && *buf && *buf != '\n') { | ||
- eol = strchrnul(buf, '\n'); | ||
- if (*eol) | ||
- eol++; | ||
- buf = eol; | ||
- } | ||
- *sublen = buf - *sub; | ||
- /* drop trailing newline, if present */ | ||
- if (*sublen && (*sub)[*sublen - 1] == '\n') | ||
- *sublen -= 1; | ||
- | ||
- /* skip any empty lines */ | ||
- while (*buf == '\n') | ||
- buf++; | ||
- *body = buf; | ||
- *bodylen = strlen(buf); | ||
- *nonsiglen = *sig - buf; | ||
-} | ||
- | ||
-/* See grab_values */ | ||
-static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz) | ||
-{ | ||
- int i; | ||
- const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL; | ||
- unsigned long sublen = 0, bodylen = 0, nonsiglen = 0, siglen = 0; | ||
- | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- const char *name = used_atom[i]; | ||
- struct atom_value *v = &val[i]; | ||
- if (!!deref != (*name == '*')) | ||
- continue; | ||
- if (deref) | ||
- name++; | ||
- if (strcmp(name, "subject") && | ||
- strcmp(name, "body") && | ||
- strcmp(name, "contents") && | ||
- strcmp(name, "contents:subject") && | ||
- strcmp(name, "contents:body") && | ||
- strcmp(name, "contents:signature")) | ||
- continue; | ||
- if (!subpos) | ||
- find_subpos(buf, sz, | ||
- &subpos, &sublen, | ||
- &bodypos, &bodylen, &nonsiglen, | ||
- &sigpos, &siglen); | ||
- | ||
- if (!strcmp(name, "subject")) | ||
- v->s = copy_subject(subpos, sublen); | ||
- else if (!strcmp(name, "contents:subject")) | ||
- v->s = copy_subject(subpos, sublen); | ||
- else if (!strcmp(name, "body")) | ||
- v->s = xmemdupz(bodypos, bodylen); | ||
- else if (!strcmp(name, "contents:body")) | ||
- v->s = xmemdupz(bodypos, nonsiglen); | ||
- else if (!strcmp(name, "contents:signature")) | ||
- v->s = xmemdupz(sigpos, siglen); | ||
- else if (!strcmp(name, "contents")) | ||
- v->s = xstrdup(subpos); | ||
- } | ||
-} | ||
- | ||
-/* | ||
- * We want to have empty print-string for field requests | ||
- * that do not apply (e.g. "authordate" for a tag object) | ||
- */ | ||
-static void fill_missing_values(struct atom_value *val) | ||
-{ | ||
- int i; | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- struct atom_value *v = &val[i]; | ||
- if (v->s == NULL) | ||
- v->s = ""; | ||
- } | ||
-} | ||
- | ||
-/* | ||
- * val is a list of atom_value to hold returned values. Extract | ||
- * the values for atoms in used_atom array out of (obj, buf, sz). | ||
- * when deref is false, (obj, buf, sz) is the object that is | ||
- * pointed at by the ref itself; otherwise it is the object the | ||
- * ref (which is a tag) refers to. | ||
- */ | ||
-static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz) | ||
-{ | ||
- grab_common_values(val, deref, obj, buf, sz); | ||
- switch (obj->type) { | ||
- case OBJ_TAG: | ||
- grab_tag_values(val, deref, obj, buf, sz); | ||
- grab_sub_body_contents(val, deref, obj, buf, sz); | ||
- grab_person("tagger", val, deref, obj, buf, sz); | ||
- break; | ||
- case OBJ_COMMIT: | ||
- grab_commit_values(val, deref, obj, buf, sz); | ||
- grab_sub_body_contents(val, deref, obj, buf, sz); | ||
- grab_person("author", val, deref, obj, buf, sz); | ||
- grab_person("committer", val, deref, obj, buf, sz); | ||
- break; | ||
- case OBJ_TREE: | ||
- /* grab_tree_values(val, deref, obj, buf, sz); */ | ||
- break; | ||
- case OBJ_BLOB: | ||
- /* grab_blob_values(val, deref, obj, buf, sz); */ | ||
- break; | ||
- default: | ||
- die("Eh? Object of type %d?", obj->type); | ||
- } | ||
-} | ||
- | ||
-static inline char *copy_advance(char *dst, const char *src) | ||
-{ | ||
- while (*src) | ||
- *dst++ = *src++; | ||
- return dst; | ||
-} | ||
- | ||
-/* | ||
- * Parse the object referred by ref, and grab needed value. | ||
- */ | ||
-static void populate_value(struct refinfo *ref) | ||
-{ | ||
- void *buf; | ||
- struct object *obj; | ||
- int eaten, i; | ||
- unsigned long size; | ||
- const unsigned char *tagged; | ||
- | ||
- ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value)); | ||
- | ||
- if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) { | ||
- unsigned char unused1[20]; | ||
- ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING, | ||
- unused1, NULL); | ||
- if (!ref->symref) | ||
- ref->symref = ""; | ||
- } | ||
- | ||
- /* Fill in specials first */ | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- const char *name = used_atom[i]; | ||
- struct atom_value *v = &ref->value[i]; | ||
- int deref = 0; | ||
- const char *refname; | ||
- const char *formatp; | ||
- struct branch *branch = NULL; | ||
- | ||
- if (*name == '*') { | ||
- deref = 1; | ||
- name++; | ||
- } | ||
- | ||
- if (starts_with(name, "refname")) | ||
- refname = ref->refname; | ||
- else if (starts_with(name, "symref")) | ||
- refname = ref->symref ? ref->symref : ""; | ||
- else if (starts_with(name, "upstream")) { | ||
- const char *branch_name; | ||
- /* only local branches may have an upstream */ | ||
- if (!skip_prefix(ref->refname, "refs/heads/", | ||
- &branch_name)) | ||
- continue; | ||
- branch = branch_get(branch_name); | ||
- | ||
- refname = branch_get_upstream(branch, NULL); | ||
- if (!refname) | ||
- continue; | ||
- } else if (starts_with(name, "push")) { | ||
- const char *branch_name; | ||
- if (!skip_prefix(ref->refname, "refs/heads/", | ||
- &branch_name)) | ||
- continue; | ||
- branch = branch_get(branch_name); | ||
- | ||
- refname = branch_get_push(branch, NULL); | ||
- if (!refname) | ||
- continue; | ||
- } else if (starts_with(name, "color:")) { | ||
- char color[COLOR_MAXLEN] = ""; | ||
- | ||
- if (color_parse(name + 6, color) < 0) | ||
- die(_("unable to parse format")); | ||
- v->s = xstrdup(color); | ||
- continue; | ||
- } else if (!strcmp(name, "flag")) { | ||
- char buf[256], *cp = buf; | ||
- if (ref->flag & REF_ISSYMREF) | ||
- cp = copy_advance(cp, ",symref"); | ||
- if (ref->flag & REF_ISPACKED) | ||
- cp = copy_advance(cp, ",packed"); | ||
- if (cp == buf) | ||
- v->s = ""; | ||
- else { | ||
- *cp = '\0'; | ||
- v->s = xstrdup(buf + 1); | ||
- } | ||
- continue; | ||
- } else if (!deref && grab_objectname(name, ref->objectname, v)) { | ||
- continue; | ||
- } else if (!strcmp(name, "HEAD")) { | ||
- const char *head; | ||
- unsigned char sha1[20]; | ||
- | ||
- head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, | ||
- sha1, NULL); | ||
- if (!strcmp(ref->refname, head)) | ||
- v->s = "*"; | ||
- else | ||
- v->s = " "; | ||
- continue; | ||
- } else | ||
- continue; | ||
- | ||
- formatp = strchr(name, ':'); | ||
- if (formatp) { | ||
- int num_ours, num_theirs; | ||
- | ||
- formatp++; | ||
- if (!strcmp(formatp, "short")) | ||
- refname = shorten_unambiguous_ref(refname, | ||
- warn_ambiguous_refs); | ||
- else if (!strcmp(formatp, "track") && | ||
- (starts_with(name, "upstream") || | ||
- starts_with(name, "push"))) { | ||
- char buf[40]; | ||
- | ||
- if (stat_tracking_info(branch, &num_ours, | ||
- &num_theirs, NULL)) | ||
- continue; | ||
- | ||
- if (!num_ours && !num_theirs) | ||
- v->s = ""; | ||
- else if (!num_ours) { | ||
- sprintf(buf, "[behind %d]", num_theirs); | ||
- v->s = xstrdup(buf); | ||
- } else if (!num_theirs) { | ||
- sprintf(buf, "[ahead %d]", num_ours); | ||
- v->s = xstrdup(buf); | ||
- } else { | ||
- sprintf(buf, "[ahead %d, behind %d]", | ||
- num_ours, num_theirs); | ||
- v->s = xstrdup(buf); | ||
- } | ||
- continue; | ||
- } else if (!strcmp(formatp, "trackshort") && | ||
- (starts_with(name, "upstream") || | ||
- starts_with(name, "push"))) { | ||
- assert(branch); | ||
- | ||
- if (stat_tracking_info(branch, &num_ours, | ||
- &num_theirs, NULL)) | ||
- continue; | ||
- | ||
- if (!num_ours && !num_theirs) | ||
- v->s = "="; | ||
- else if (!num_ours) | ||
- v->s = "<"; | ||
- else if (!num_theirs) | ||
- v->s = ">"; | ||
- else | ||
- v->s = "<>"; | ||
- continue; | ||
- } else | ||
- die("unknown %.*s format %s", | ||
- (int)(formatp - name), name, formatp); | ||
- } | ||
- | ||
- if (!deref) | ||
- v->s = refname; | ||
- else { | ||
- int len = strlen(refname); | ||
- char *s = xmalloc(len + 4); | ||
- sprintf(s, "%s^{}", refname); | ||
- v->s = s; | ||
- } | ||
- } | ||
- | ||
- for (i = 0; i < used_atom_cnt; i++) { | ||
- struct atom_value *v = &ref->value[i]; | ||
- if (v->s == NULL) | ||
- goto need_obj; | ||
- } | ||
- return; | ||
- | ||
- need_obj: | ||
- buf = get_obj(ref->objectname, &obj, &size, &eaten); | ||
- if (!buf) | ||
- die("missing object %s for %s", | ||
- sha1_to_hex(ref->objectname), ref->refname); | ||
- if (!obj) | ||
- die("parse_object_buffer failed on %s for %s", | ||
- sha1_to_hex(ref->objectname), ref->refname); | ||
- | ||
- grab_values(ref->value, 0, obj, buf, size); | ||
- if (!eaten) | ||
- free(buf); | ||
- | ||
- /* | ||
- * If there is no atom that wants to know about tagged | ||
- * object, we are done. | ||
- */ | ||
- if (!need_tagged || (obj->type != OBJ_TAG)) | ||
- return; | ||
- | ||
- /* | ||
- * If it is a tag object, see if we use a value that derefs | ||
- * the object, and if we do grab the object it refers to. | ||
- */ | ||
- tagged = ((struct tag *)obj)->tagged->sha1; | ||
- | ||
- /* | ||
- * NEEDSWORK: This derefs tag only once, which | ||
- * is good to deal with chains of trust, but | ||
- * is not consistent with what deref_tag() does | ||
- * which peels the onion to the core. | ||
- */ | ||
- buf = get_obj(tagged, &obj, &size, &eaten); | ||
- if (!buf) | ||
- die("missing object %s for %s", | ||
- sha1_to_hex(tagged), ref->refname); | ||
- if (!obj) | ||
- die("parse_object_buffer failed on %s for %s", | ||
- sha1_to_hex(tagged), ref->refname); | ||
- grab_values(ref->value, 1, obj, buf, size); | ||
- if (!eaten) | ||
- free(buf); | ||
-} | ||
- | ||
-/* | ||
- * Given a ref, return the value for the atom. This lazily gets value | ||
- * out of the object by calling populate value. | ||
- */ | ||
-static void get_value(struct refinfo *ref, int atom, struct atom_value **v) | ||
-{ | ||
- if (!ref->value) { | ||
- populate_value(ref); | ||
- fill_missing_values(ref->value); | ||
- } | ||
- *v = &ref->value[atom]; | ||
-} | ||
- | ||
-struct grab_ref_cbdata { | ||
- struct refinfo **grab_array; | ||
- const char **grab_pattern; | ||
- int grab_cnt; | ||
-}; | ||
- | ||
-/* | ||
- * A call-back given to for_each_ref(). Filter refs and keep them for | ||
- * later object processing. | ||
- */ | ||
-static int grab_single_ref(const char *refname, const struct object_id *oid, | ||
- int flag, void *cb_data) | ||
-{ | ||
- struct grab_ref_cbdata *cb = cb_data; | ||
- struct refinfo *ref; | ||
- int cnt; | ||
- | ||
- if (flag & REF_BAD_NAME) { | ||
- warning("ignoring ref with broken name %s", refname); | ||
- return 0; | ||
- } | ||
- | ||
- if (flag & REF_ISBROKEN) { | ||
- warning("ignoring broken ref %s", refname); | ||
- return 0; | ||
- } | ||
- | ||
- if (*cb->grab_pattern) { | ||
- const char **pattern; | ||
- int namelen = strlen(refname); | ||
- for (pattern = cb->grab_pattern; *pattern; pattern++) { | ||
- const char *p = *pattern; | ||
- int plen = strlen(p); | ||
- | ||
- if ((plen <= namelen) && | ||
- !strncmp(refname, p, plen) && | ||
- (refname[plen] == '\0' || | ||
- refname[plen] == '/' || | ||
- p[plen-1] == '/')) | ||
- break; | ||
- if (!wildmatch(p, refname, WM_PATHNAME, NULL)) | ||
- break; | ||
- } | ||
- if (!*pattern) | ||
- return 0; | ||
- } | ||
- | ||
- /* | ||
- * We do not open the object yet; sort may only need refname | ||
- * to do its job and the resulting list may yet to be pruned | ||
- * by maxcount logic. | ||
- */ | ||
- ref = xcalloc(1, sizeof(*ref)); | ||
- ref->refname = xstrdup(refname); | ||
- hashcpy(ref->objectname, oid->hash); | ||
- ref->flag = flag; | ||
- | ||
- cnt = cb->grab_cnt; | ||
- REALLOC_ARRAY(cb->grab_array, cnt + 1); | ||
- cb->grab_array[cnt++] = ref; | ||
- cb->grab_cnt = cnt; | ||
- return 0; | ||
-} | ||
- | ||
-static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b) | ||
-{ | ||
- struct atom_value *va, *vb; | ||
- int cmp; | ||
- cmp_type cmp_type = used_atom_type[s->atom]; | ||
- | ||
- get_value(a, s->atom, &va); | ||
- get_value(b, s->atom, &vb); | ||
- switch (cmp_type) { | ||
- case FIELD_STR: | ||
- cmp = strcmp(va->s, vb->s); | ||
- break; | ||
- default: | ||
- if (va->ul < vb->ul) | ||
- cmp = -1; | ||
- else if (va->ul == vb->ul) | ||
- cmp = 0; | ||
- else | ||
- cmp = 1; | ||
- break; | ||
- } | ||
- return (s->reverse) ? -cmp : cmp; | ||
-} | ||
- | ||
-static struct ref_sort *ref_sort; | ||
-static int compare_refs(const void *a_, const void *b_) | ||
-{ | ||
- struct refinfo *a = *((struct refinfo **)a_); | ||
- struct refinfo *b = *((struct refinfo **)b_); | ||
- struct ref_sort *s; | ||
- | ||
- for (s = ref_sort; s; s = s->next) { | ||
- int cmp = cmp_ref_sort(s, a, b); | ||
- if (cmp) | ||
- return cmp; | ||
- } | ||
- return 0; | ||
-} | ||
- | ||
-static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs) | ||
-{ | ||
- ref_sort = sort; | ||
- qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs); | ||
-} | ||
- | ||
-static void print_value(struct atom_value *v, int quote_style) | ||
-{ | ||
- struct strbuf sb = STRBUF_INIT; | ||
- switch (quote_style) { | ||
- case QUOTE_NONE: | ||
- fputs(v->s, stdout); | ||
- break; | ||
- case QUOTE_SHELL: | ||
- sq_quote_buf(&sb, v->s); | ||
- break; | ||
- case QUOTE_PERL: | ||
- perl_quote_buf(&sb, v->s); | ||
- break; | ||
- case QUOTE_PYTHON: | ||
- python_quote_buf(&sb, v->s); | ||
- break; | ||
- case QUOTE_TCL: | ||
- tcl_quote_buf(&sb, v->s); | ||
- break; | ||
- } | ||
- if (quote_style != QUOTE_NONE) { | ||
- fputs(sb.buf, stdout); | ||
- strbuf_release(&sb); | ||
- } | ||
-} | ||
- | ||
-static int hex1(char ch) | ||
-{ | ||
- if ('0' <= ch && ch <= '9') | ||
- return ch - '0'; | ||
- else if ('a' <= ch && ch <= 'f') | ||
- return ch - 'a' + 10; | ||
- else if ('A' <= ch && ch <= 'F') | ||
- return ch - 'A' + 10; | ||
- return -1; | ||
-} | ||
-static int hex2(const char *cp) | ||
-{ | ||
- if (cp[0] && cp[1]) | ||
- return (hex1(cp[0]) << 4) | hex1(cp[1]); | ||
- else | ||
- return -1; | ||
-} | ||
- | ||
-static void emit(const char *cp, const char *ep) | ||
-{ | ||
- while (*cp && (!ep || cp < ep)) { | ||
- if (*cp == '%') { | ||
- if (cp[1] == '%') | ||
- cp++; | ||
- else { | ||
- int ch = hex2(cp + 1); | ||
- if (0 <= ch) { | ||
- putchar(ch); | ||
- cp += 3; | ||
- continue; | ||
- } | ||
- } | ||
- } | ||
- putchar(*cp); | ||
- cp++; | ||
- } | ||
-} | ||
- | ||
-static void show_ref(struct refinfo *info, const char *format, int quote_style) | ||
-{ | ||
- const char *cp, *sp, *ep; | ||
- | ||
- for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) { | ||
- struct atom_value *atomv; | ||
- | ||
- ep = strchr(sp, ')'); | ||
- if (cp < sp) | ||
- emit(cp, sp); | ||
- get_value(info, parse_atom(sp + 2, ep), &atomv); | ||
- print_value(atomv, quote_style); | ||
- } | ||
- if (*cp) { | ||
- sp = cp + strlen(cp); | ||
- emit(cp, sp); | ||
- } | ||
- if (need_color_reset_at_eol) { | ||
- struct atom_value resetv; | ||
- char color[COLOR_MAXLEN] = ""; | ||
- | ||
- if (color_parse("reset", color) < 0) | ||
- die("BUG: couldn't parse 'reset' as a color"); | ||
- resetv.s = color; | ||
- print_value(&resetv, quote_style); | ||
- } | ||
- putchar('\n'); | ||
-} | ||
- | ||
-static struct ref_sort *default_sort(void) | ||
-{ | ||
- static const char cstr_name[] = "refname"; | ||
- | ||
- struct ref_sort *sort = xcalloc(1, sizeof(*sort)); | ||
- | ||
- sort->next = NULL; | ||
- sort->atom = parse_atom(cstr_name, cstr_name + strlen(cstr_name)); | ||
- return sort; | ||
-} | ||
- | ||
-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; | ||
- int len; | ||
- | ||
- if (!arg) /* should --no-sort void the list ? */ | ||
- return -1; | ||
- | ||
- s = xcalloc(1, sizeof(*s)); | ||
- s->next = *sort_tail; | ||
- *sort_tail = s; | ||
- | ||
- if (*arg == '-') { | ||
- s->reverse = 1; | ||
- arg++; | ||
- } | ||
- len = strlen(arg); | ||
- s->atom = parse_atom(arg, arg+len); | ||
- return 0; | ||
-} | ||
+#include "ref-filter.h" | ||
static char const * const for_each_ref_usage[] = { | ||
N_("git for-each-ref [<options>] [<pattern>]"), | ||
@@ -1086,12 +12,12 @@ static char const * const for_each_ref_usage[] = { | ||
int cmd_for_each_ref(int argc, const char **argv, const char *prefix) | ||
{ | ||
- int i, num_refs; | ||
+ int i; | ||
const char *format = "%(objectname) %(objecttype)\t%(refname)"; | ||
- struct ref_sort *sort = NULL, **sort_tail = &sort; | ||
+ struct ref_sorting *sorting = NULL, **sorting_tail = &sorting; | ||
int maxcount = 0, quote_style = 0; | ||
- struct refinfo **refs; | ||
- struct grab_ref_cbdata cbdata; | ||
+ struct ref_array array; | ||
+ struct ref_filter filter; | ||
struct option opts[] = { | ||
OPT_BIT('s', "shell", "e_style, | ||
@@ -1106,8 +32,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) | ||
OPT_GROUP(""), | ||
OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")), | ||
OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")), | ||
- OPT_CALLBACK(0 , "sort", sort_tail, N_("key"), | ||
- N_("field name to sort on"), &opt_parse_sort), | ||
+ OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"), | ||
+ N_("field name to sort on"), &parse_opt_ref_sorting), | ||
OPT_END(), | ||
}; | ||
@@ -1120,26 +46,25 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) | ||
error("more than one quoting style?"); | ||
usage_with_options(for_each_ref_usage, opts); | ||
} | ||
- if (verify_format(format)) | ||
+ if (verify_ref_format(format)) | ||
usage_with_options(for_each_ref_usage, opts); | ||
- if (!sort) | ||
- sort = default_sort(); | ||
+ if (!sorting) | ||
+ sorting = ref_default_sorting(); | ||
/* for warn_ambiguous_refs */ | ||
git_config(git_default_config, NULL); | ||
- memset(&cbdata, 0, sizeof(cbdata)); | ||
- cbdata.grab_pattern = argv; | ||
- for_each_rawref(grab_single_ref, &cbdata); | ||
- refs = cbdata.grab_array; | ||
- num_refs = cbdata.grab_cnt; | ||
- | ||
- sort_refs(sort, refs, num_refs); | ||
+ memset(&array, 0, sizeof(array)); | ||
+ memset(&filter, 0, sizeof(filter)); | ||
+ filter.name_patterns = argv; | ||
+ filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN); | ||
+ ref_array_sort(sorting, &array); | ||
- if (!maxcount || num_refs < maxcount) | ||
- maxcount = num_refs; | ||
+ if (!maxcount || array.nr < maxcount) | ||
+ maxcount = array.nr; | ||
for (i = 0; i < maxcount; i++) | ||
- show_ref(refs[i], format, quote_style); | ||
+ show_ref_array_item(array.items[i], format, quote_style); | ||
+ ref_array_clear(&array); | ||
return 0; | ||
} |
View
82
builtin/fsck.c
@@ -23,8 +23,11 @@ static int show_tags; | ||
static int show_unreachable; | ||
static int include_reflogs = 1; | ||
static int check_full = 1; | ||
+static int connectivity_only; | ||
static int check_strict; | ||
static int keep_cache_objects; | ||
+static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT; | ||
+static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT; | ||
static struct object_id head_oid; | ||
static const char *head_points_at; | ||
static int errors_found; | ||
@@ -44,39 +47,52 @@ static int show_dangling = 1; | ||
#define DIRENT_SORT_HINT(de) ((de)->d_ino) | ||
#endif | ||
-static void objreport(struct object *obj, const char *severity, | ||
- const char *err, va_list params) | ||
+static int fsck_config(const char *var, const char *value, void *cb) | ||
{ | ||
- fprintf(stderr, "%s in %s %s: ", | ||
- severity, typename(obj->type), sha1_to_hex(obj->sha1)); | ||
- vfprintf(stderr, err, params); | ||
- fputs("\n", stderr); | ||
+ if (strcmp(var, "fsck.skiplist") == 0) { | ||
+ const char *path; | ||
+ struct strbuf sb = STRBUF_INIT; | ||
+ | ||
+ if (git_config_pathname(&path, var, value)) | ||
+ return 1; | ||
+ strbuf_addf(&sb, "skiplist=%s", path); | ||
+ free((char *)path); | ||
+ fsck_set_msg_types(&fsck_obj_options, sb.buf); | ||
+ strbuf_release(&sb); | ||
+ return 0; | ||
+ } | ||
+ | ||
+ if (skip_prefix(var, "fsck.", &var)) { | ||
+ fsck_set_msg_type(&fsck_obj_options, var, value); | ||
+ return 0; | ||
+ } | ||
+ | ||
+ return git_default_config(var, value, cb); | ||
+} | ||
+ | ||
+static void objreport(struct object *obj, const char *msg_type, | ||
+ const char *err) | ||
+{ | ||
+ fprintf(stderr, "%s in %s %s: %s\n", | ||
+ msg_type, typename(obj->type), sha1_to_hex(obj->sha1), err); | ||
} | ||
-__attribute__((format (printf, 2, 3))) | ||
-static int objerror(struct object *obj, const char *err, ...) | ||
+static int objerror(struct object *obj, const char *err) | ||
{ | ||
- va_list params; | ||
- va_start(params, err); | ||
errors_found |= ERROR_OBJECT; | ||
- objreport(obj, "error", err, params); | ||
- va_end(params); | ||
+ objreport(obj, "error", err); | ||
return -1; | ||
} | ||
-__attribute__((format (printf, 3, 4))) | ||
-static int fsck_error_func(struct object *obj, int type, const char *err, ...) | ||
+static int fsck_error_func(struct object *obj, int type, const char *message) | ||
{ | ||
- va_list params; | ||
- va_start(params, err); | ||
- objreport(obj, (type == FSCK_WARN) ? "warning" : "error", err, params); | ||
- va_end(params); | ||
+ objreport(obj, (type == FSCK_WARN) ? "warning" : "error", message); | ||
return (type == FSCK_WARN) ? 0 : 1; | ||
} | ||
static struct object_array pending; | ||
-static int mark_object(struct object *obj, int type, void *data) | ||
+static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options) | ||
{ | ||
struct object *parent = data; | ||
@@ -119,7 +135,7 @@ static int mark_object(struct object *obj, int type, void *data) | ||
static void mark_object_reachable(struct object *obj) | ||
{ | ||
- mark_object(obj, OBJ_ANY, NULL); | ||
+ mark_object(obj, OBJ_ANY, NULL, NULL); | ||
} | ||
static int traverse_one_object(struct object *obj) | ||
@@ -132,7 +148,7 @@ static int traverse_one_object(struct object *obj) | ||
if (parse_tree(tree) < 0) | ||
return 1; /* error already displayed */ | ||
} | ||
- result = fsck_walk(obj, mark_object, obj); | ||
+ result = fsck_walk(obj, obj, &fsck_walk_options); | ||
if (tree) | ||
free_tree_buffer(tree); | ||
return result; | ||
@@ -158,7 +174,7 @@ static int traverse_reachable(void) | ||
return !!result; | ||
} | ||
-static int mark_used(struct object *obj, int type, void *data) | ||
+static int mark_used(struct object *obj, int type, void *data, struct fsck_options *options) | ||
{ | ||
if (!obj) | ||
return 1; | ||
@@ -179,6 +195,8 @@ static void check_reachable_object(struct object *obj) | ||
if (!(obj->flags & HAS_OBJ)) { | ||
if (has_sha1_pack(obj->sha1)) | ||
return; /* it is in pack - forget about it */ | ||
+ if (connectivity_only && has_sha1_file(obj->sha1)) | ||
+ return; | ||
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); | ||
errors_found |= ERROR_REACHABLE; | ||
return; | ||
@@ -225,13 +243,14 @@ static void check_unreachable_object(struct object *obj) | ||
printf("dangling %s %s\n", typename(obj->type), | ||
sha1_to_hex(obj->sha1)); | ||
if (write_lost_and_found) { | ||
- const char *filename = git_path("lost-found/%s/%s", | ||
+ char *filename = git_pathdup("lost-found/%s/%s", | ||
obj->type == OBJ_COMMIT ? "commit" : "other", | ||
sha1_to_hex(obj->sha1)); | ||
FILE *f; | ||
if (safe_create_leading_directories_const(filename)) { | ||
error("Could not create lost-found"); | ||
+ free(filename); | ||
return; | ||
} | ||
if (!(f = fopen(filename, "w"))) | ||
@@ -244,6 +263,7 @@ static void check_unreachable_object(struct object *obj) | ||
if (fclose(f)) | ||
die_errno("Could not finish '%s'", | ||
filename); | ||
+ free(filename); | ||
} | ||
return; | ||
} | ||
@@ -296,9 +316,9 @@ static int fsck_obj(struct object *obj) | ||
fprintf(stderr, "Checking %s %s\n", | ||
typename(obj->type), sha1_to_hex(obj->sha1)); | ||
- if (fsck_walk(obj, mark_used, NULL)) | ||
+ if (fsck_walk(obj, NULL, &fsck_obj_options)) | ||
objerror(obj, "broken links"); | ||
- if (fsck_object(obj, NULL, 0, check_strict, fsck_error_func)) | ||
+ if (fsck_object(obj, NULL, 0, &fsck_obj_options)) | ||
return -1; | ||
if (obj->type == OBJ_TREE) { | ||
@@ -621,6 +641,7 @@ static struct option fsck_opts[] = { | ||
OPT_BOOL(0, "cache", &keep_cache_objects, N_("make index objects head nodes")), | ||
OPT_BOOL(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")), | ||
OPT_BOOL(0, "full", &check_full, N_("also consider packs and alternate objects")), | ||
+ OPT_BOOL(0, "connectivity-only", &connectivity_only, N_("check only connectivity")), | ||
OPT_BOOL(0, "strict", &check_strict, N_("enable more strict checking")), | ||
OPT_BOOL(0, "lost-found", &write_lost_and_found, | ||
N_("write dangling objects in .git/lost-found")), | ||
@@ -638,6 +659,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) | ||
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); | ||
+ fsck_walk_options.walk = mark_object; | ||
+ fsck_obj_options.walk = mark_used; | ||
+ fsck_obj_options.error_func = fsck_error_func; | ||
+ if (check_strict) | ||
+ fsck_obj_options.strict = 1; | ||
+ | ||
if (show_progress == -1) | ||
show_progress = isatty(2); | ||
if (verbose) | ||
@@ -648,8 +675,11 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) | ||
include_reflogs = 0; | ||
} | ||
+ git_config(fsck_config, NULL); | ||
+ | ||
fsck_head_link(); | ||
- fsck_object_dir(get_object_directory()); | ||
+ if (!connectivity_only) | ||
+ fsck_object_dir(get_object_directory()); | ||
prepare_alt_odb(); | ||
for (alt = alt_odb_list; alt; alt = alt->next) { | ||
View
34
builtin/gc.c
@@ -11,6 +11,7 @@ | ||
*/ | ||
#include "builtin.h" | ||
+#include "tempfile.h" | ||
#include "lockfile.h" | ||
#include "parse-options.h" | ||
#include "run-command.h" | ||
@@ -42,20 +43,7 @@ static struct argv_array prune = ARGV_ARRAY_INIT; | ||
static struct argv_array prune_worktrees = ARGV_ARRAY_INIT; | ||
static struct argv_array rerere = ARGV_ARRAY_INIT; | ||
-static char *pidfile; | ||
- | ||
-static void remove_pidfile(void) | ||
-{ | ||
- if (pidfile) | ||
- unlink(pidfile); | ||
-} | ||
- | ||
-static void remove_pidfile_on_signal(int signo) | ||
-{ | ||
- remove_pidfile(); | ||
- sigchain_pop(signo); | ||
- raise(signo); | ||
-} | ||
+static struct tempfile pidfile; | ||
static void git_config_date_string(const char *key, const char **output) | ||
{ | ||
@@ -85,7 +73,7 @@ static void gc_config(void) | ||
git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit); | ||
git_config_get_bool("gc.autodetach", &detach_auto); | ||
git_config_date_string("gc.pruneexpire", &prune_expire); | ||
- git_config_date_string("gc.pruneworktreesexpire", &prune_worktrees_expire); | ||
+ git_config_date_string("gc.worktreepruneexpire", &prune_worktrees_expire); | ||
git_config(git_default_config, NULL); | ||
} | ||
@@ -199,20 +187,22 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) | ||
uintmax_t pid; | ||
FILE *fp; | ||
int fd; | ||
+ char *pidfile_path; | ||
- if (pidfile) | ||
+ if (is_tempfile_active(&pidfile)) | ||
/* already locked */ | ||
return NULL; | ||
if (gethostname(my_host, sizeof(my_host))) | ||
strcpy(my_host, "unknown"); | ||
- fd = hold_lock_file_for_update(&lock, git_path("gc.pid"), | ||
+ pidfile_path = git_pathdup("gc.pid"); | ||
+ fd = hold_lock_file_for_update(&lock, pidfile_path, | ||
LOCK_DIE_ON_ERROR); | ||
if (!force) { | ||
static char locking_host[128]; | ||
int should_exit; | ||
- fp = fopen(git_path("gc.pid"), "r"); | ||
+ fp = fopen(pidfile_path, "r"); | ||
memset(locking_host, 0, sizeof(locking_host)); | ||
should_exit = | ||
fp != NULL && | ||
@@ -236,6 +226,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) | ||
if (fd >= 0) | ||
rollback_lock_file(&lock); | ||
*ret_pid = pid; | ||
+ free(pidfile_path); | ||
return locking_host; | ||
} | ||
} | ||
@@ -245,11 +236,8 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) | ||
write_in_full(fd, sb.buf, sb.len); | ||
strbuf_release(&sb); | ||
commit_lock_file(&lock); | ||
- | ||
- pidfile = git_pathdup("gc.pid"); | ||
- sigchain_push_common(remove_pidfile_on_signal); | ||
- atexit(remove_pidfile); | ||
- | ||
+ register_tempfile(&pidfile, pidfile_path); | ||
+ free(pidfile_path); | ||
return NULL; | ||
} | ||
View
17
builtin/index-pack.c
@@ -75,6 +75,7 @@ static int nr_threads; | ||
static int from_stdin; | ||
static int strict; | ||
static int do_fsck_object; | ||
+static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; | ||
static int verbose; | ||
static int show_stat; | ||
static int check_self_contained_and_connected; | ||
@@ -192,7 +193,7 @@ static void cleanup_thread(void) | ||
#endif | ||
-static int mark_link(struct object *obj, int type, void *data) | ||
+static int mark_link(struct object *obj, int type, void *data, struct fsck_options *options) | ||
{ | ||
if (!obj) | ||
return -1; | ||
@@ -838,10 +839,9 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, | ||
if (!obj) | ||
die(_("invalid %s"), typename(type)); | ||
if (do_fsck_object && | ||
- fsck_object(obj, buf, size, 1, | ||
- fsck_error_function)) | ||
+ fsck_object(obj, buf, size, &fsck_options)) | ||
die(_("Error in object")); | ||
- if (fsck_walk(obj, mark_link, NULL)) | ||
+ if (fsck_walk(obj, NULL, &fsck_options)) | ||
die(_("Not all child objects of %s are reachable"), sha1_to_hex(obj->sha1)); | ||
if (obj->type == OBJ_TREE) { | ||
@@ -1421,7 +1421,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name, | ||
get_object_directory(), sha1_to_hex(sha1)); | ||
final_pack_name = name; | ||
} | ||
- if (move_temp_to_file(curr_pack_name, final_pack_name)) | ||
+ if (finalize_object_file(curr_pack_name, final_pack_name)) | ||
die(_("cannot store pack file")); | ||
} else if (from_stdin) | ||
chmod(final_pack_name, 0444); | ||
@@ -1432,7 +1432,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name, | ||
get_object_directory(), sha1_to_hex(sha1)); | ||
final_index_name = name; | ||
} | ||
- if (move_temp_to_file(curr_index_name, final_index_name)) | ||
+ if (finalize_object_file(curr_index_name, final_index_name)) | ||
die(_("cannot store index file")); | ||
} else | ||
chmod(final_index_name, 0444); | ||
@@ -1615,6 +1615,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) | ||
usage(index_pack_usage); | ||
check_replace_refs = 0; | ||
+ fsck_options.walk = mark_link; | ||
reset_pack_idx_option(&opts); | ||
git_config(git_index_pack_config, &opts); | ||
@@ -1632,6 +1633,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) | ||
} else if (!strcmp(arg, "--strict")) { | ||
strict = 1; | ||
do_fsck_object = 1; | ||
+ } else if (skip_prefix(arg, "--strict=", &arg)) { | ||
+ strict = 1; | ||
+ do_fsck_object = 1; | ||
+ fsck_set_msg_types(&fsck_options, arg); | ||
} else if (!strcmp(arg, "--check-self-contained-and-connected")) { | ||
strict = 1; | ||
check_self_contained_and_connected = 1; | ||
View
3
builtin/init-db.c
@@ -4,6 +4,7 @@ | ||
* Copyright (C) Linus Torvalds, 2005 | ||
*/ | ||
#include "cache.h" | ||
+#include "refs.h" | ||
#include "builtin.h" | ||
#include "exec_cmd.h" | ||
#include "parse-options.h" | ||
@@ -377,7 +378,7 @@ static void separate_git_dir(const char *git_dir) | ||
die_errno(_("unable to move %s to %s"), src, git_dir); | ||
} | ||
- write_file(git_link, 1, "gitdir: %s\n", git_dir); | ||
+ write_file(git_link, "gitdir: %s", git_dir); | ||
} | ||
int init_db(const char *template_dir, unsigned int flags) | ||
View
40
builtin/log.c
@@ -5,6 +5,7 @@ | ||
* 2006 Junio Hamano | ||
*/ | ||
#include "cache.h" | ||
+#include "refs.h" | ||
#include "color.h" | ||
#include "commit.h" | ||
#include "diff.h" | ||
@@ -31,6 +32,7 @@ static const char *default_date_mode = NULL; | ||
static int default_abbrev_commit; | ||
static int default_show_root = 1; | ||
+static int default_follow; | ||
static int decoration_style; | ||
static int decoration_given; | ||
static int use_mailmap_config; | ||
@@ -102,6 +104,8 @@ static void cmd_log_init_defaults(struct rev_info *rev) | ||
{ | ||
if (fmt_pretty) | ||
get_commit_format(fmt_pretty, rev); | ||
+ if (default_follow) | ||
+ DIFF_OPT_SET(&rev->diffopt, DEFAULT_FOLLOW_RENAMES); | ||
rev->verbose_header = 1; | ||
DIFF_OPT_SET(&rev->diffopt, RECURSIVE); | ||
rev->diffopt.stat_width = -1; /* use full terminal width */ | ||
@@ -112,7 +116,7 @@ static void cmd_log_init_defaults(struct rev_info *rev) | ||
DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV); | ||
if (default_date_mode) | ||
- rev->date_mode = parse_date_format(default_date_mode); | ||
+ parse_date_format(default_date_mode, &rev->date_mode); | ||
rev->diffopt.touched_flags = 0; | ||
} | ||
@@ -338,8 +342,7 @@ static int cmd_log_walk(struct rev_info *rev) | ||
* retain that state information if replacing rev->diffopt in this loop | ||
*/ | ||
while ((commit = get_revision(rev)) != NULL) { | ||
- if (!log_tree_commit(rev, commit) && | ||
- rev->max_count >= 0) | ||
+ if (!log_tree_commit(rev, commit) && rev->max_count >= 0) | ||
/* | ||
* We decremented max_count in get_revision, | ||
* but we didn't actually show the commit. | ||
@@ -390,6 +393,10 @@ static int git_log_config(const char *var, const char *value, void *cb) | ||
default_show_root = git_config_bool(var, value); | ||
return 0; | ||
} | ||
+ if (!strcmp(var, "log.follow")) { | ||
+ default_follow = git_config_bool(var, value); | ||
+ return 0; | ||
+ } | ||
if (skip_prefix(var, "color.decorate.", &slot_name)) | ||
return parse_decorate_color_config(var, slot_name, value); | ||
if (!strcmp(var, "log.mailmap")) { | ||
@@ -496,7 +503,8 @@ static int show_tree_object(const unsigned char *sha1, | ||
return 0; | ||
} | ||
-static void show_rev_tweak_rev(struct rev_info *rev, struct setup_revision_opt *opt) | ||
+static void show_setup_revisions_tweak(struct rev_info *rev, | ||
+ struct setup_revision_opt *opt) | ||
{ | ||
if (rev->ignore_merges) { | ||
/* There was no "-m" on the command line */ | ||
@@ -531,7 +539,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) | ||
memset(&opt, 0, sizeof(opt)); | ||
opt.def = "HEAD"; | ||
- opt.tweak = show_rev_tweak_rev; | ||
+ opt.tweak = show_setup_revisions_tweak; | ||
cmd_log_init(argc, argv, prefix, &rev, &opt); | ||
if (!rev.no_walk) | ||
@@ -618,6 +626,22 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) | ||
return cmd_log_walk(&rev); | ||
} | ||
+static void log_setup_revisions_tweak(struct rev_info *rev, | ||
+ struct setup_revision_opt *opt) | ||
+{ | ||
+ if (DIFF_OPT_TST(&rev->diffopt, DEFAULT_FOLLOW_RENAMES) && | ||
+ rev->prune_data.nr == 1) | ||
+ DIFF_OPT_SET(&rev->diffopt, FOLLOW_RENAMES); | ||
+ | ||
+ /* Turn --cc/-c into -p --cc/-c when -p was not given */ | ||
+ if (!rev->diffopt.output_format && rev->combine_merges) | ||
+ rev->diffopt.output_format = DIFF_FORMAT_PATCH; | ||
+ | ||
+ /* Turn -m on when --cc/-c was given */ | ||
+ if (rev->combine_merges) | ||
+ rev->ignore_merges = 0; | ||
+} | ||
+ | ||
int cmd_log(int argc, const char **argv, const char *prefix) | ||
{ | ||
struct rev_info rev; | ||
@@ -631,6 +655,7 @@ int cmd_log(int argc, const char **argv, const char *prefix) | ||
memset(&opt, 0, sizeof(opt)); | ||
opt.def = "HEAD"; | ||
opt.revarg_opt = REVARG_COMMITTISH; | ||
+ opt.tweak = log_setup_revisions_tweak; | ||
cmd_log_init(argc, argv, prefix, &rev, &opt); | ||
return cmd_log_walk(&rev); | ||
} | ||
@@ -939,7 +964,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, | ||
msg = body; | ||
pp.fmt = CMIT_FMT_EMAIL; | ||
- pp.date_mode = DATE_RFC2822; | ||
+ pp.date_mode.type = DATE_RFC2822; | ||
pp_user_info(&pp, NULL, &sb, committer, encoding); | ||
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte); | ||
pp_remainder(&pp, &msg, &sb, 0); | ||
@@ -1438,8 +1463,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) | ||
continue; | ||
} | ||
- if (ignore_if_in_upstream && | ||
- has_commit_patch_id(commit, &ids)) | ||
+ if (ignore_if_in_upstream && has_commit_patch_id(commit, &ids)) | ||
continue; | ||
nr++; | ||
View
2
builtin/ls-files.c
@@ -516,7 +516,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) | ||
/* Treat unmatching pathspec elements as errors */ | ||
if (pathspec.nr && error_unmatch) | ||
- ps_matched = xcalloc(1, pathspec.nr); | ||
+ ps_matched = xcalloc(pathspec.nr, 1); | ||
if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) | ||
die("ls-files --ignored needs some exclude pattern"); | ||
View
30
builtin/merge.c
@@ -231,9 +231,9 @@ static struct option builtin_merge_options[] = { | ||
/* Cleans up metadata that is uninteresting after a succeeded merge. */ | ||
static void drop_save(void) | ||
{ | ||
- unlink(git_path("MERGE_HEAD")); | ||
- unlink(git_path("MERGE_MSG")); | ||
- unlink(git_path("MERGE_MODE")); | ||
+ unlink(git_path_merge_head()); | ||
+ unlink(git_path_merge_msg()); | ||
+ unlink(git_path_merge_mode()); | ||
} | ||
static int save_state(unsigned char *stash) | ||
@@ -338,7 +338,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead | ||
struct pretty_print_context ctx = {0}; | ||
printf(_("Squash commit -- not updating HEAD\n")); | ||
- filename = git_path("SQUASH_MSG"); | ||
+ filename = git_path_squash_msg(); | ||
fd = open(filename, O_WRONLY | O_CREAT, 0666); | ||
if (fd < 0) | ||
die_errno(_("Could not write to '%s'"), filename); | ||
@@ -754,7 +754,7 @@ static void add_strategies(const char *string, unsigned attr) | ||
static void write_merge_msg(struct strbuf *msg) | ||
{ | ||
- const char *filename = git_path("MERGE_MSG"); | ||
+ const char *filename = git_path_merge_msg(); | ||
int fd = open(filename, O_WRONLY | O_CREAT, 0666); | ||
if (fd < 0) | ||
die_errno(_("Could not open '%s' for writing"), | ||
@@ -766,7 +766,7 @@ static void write_merge_msg(struct strbuf *msg) | ||
static void read_merge_msg(struct strbuf *msg) | ||
{ | ||
- const char *filename = git_path("MERGE_MSG"); | ||
+ const char *filename = git_path_merge_msg(); | ||
strbuf_reset(msg); | ||
if (strbuf_read_file(msg, filename, 0) < 0) | ||
die_errno(_("Could not read from '%s'"), filename); | ||
@@ -799,10 +799,10 @@ static void prepare_to_commit(struct commit_list *remoteheads) | ||
strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char); | ||
write_merge_msg(&msg); | ||
if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg", | ||
- git_path("MERGE_MSG"), "merge", NULL)) | ||
+ git_path_merge_msg(), "merge", NULL)) | ||
abort_commit(remoteheads, NULL); | ||
if (0 < option_edit) { | ||
- if (launch_editor(git_path("MERGE_MSG"), NULL, NULL)) | ||
+ if (launch_editor(git_path_merge_msg(), NULL, NULL)) | ||
abort_commit(remoteheads, NULL); | ||
} | ||
read_merge_msg(&msg); | ||
@@ -865,7 +865,7 @@ static int suggest_conflicts(void) | ||
FILE *fp; | ||
struct strbuf msgbuf = STRBUF_INIT; | ||
- filename = git_path("MERGE_MSG"); | ||
+ filename = git_path_merge_msg(); | ||
fp = fopen(filename, "a"); | ||
if (!fp) | ||
die_errno(_("Could not open '%s' for writing"), filename); | ||
@@ -967,7 +967,7 @@ static void write_merge_state(struct commit_list *remoteheads) | ||
} | ||
strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1)); | ||
} | ||
- filename = git_path("MERGE_HEAD"); | ||
+ filename = git_path_merge_head(); | ||
fd = open(filename, O_WRONLY | O_CREAT, 0666); | ||
if (fd < 0) | ||
die_errno(_("Could not open '%s' for writing"), filename); | ||
@@ -977,7 +977,7 @@ static void write_merge_state(struct commit_list *remoteheads) | ||
strbuf_addch(&merge_msg, '\n'); | ||
write_merge_msg(&merge_msg); | ||
- filename = git_path("MERGE_MODE"); | ||
+ filename = git_path_merge_mode(); | ||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); | ||
if (fd < 0) | ||
die_errno(_("Could not open '%s' for writing"), filename); | ||
@@ -1070,7 +1070,7 @@ static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge | ||
if (!merge_names) | ||
merge_names = &fetch_head_file; | ||
- filename = git_path("FETCH_HEAD"); | ||
+ filename = git_path_fetch_head(); | ||
fd = open(filename, O_RDONLY); | ||
if (fd < 0) | ||
die_errno(_("could not open '%s' for reading"), filename); | ||
@@ -1204,7 +1204,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) | ||
int nargc = 2; | ||
const char *nargv[] = {"reset", "--merge", NULL}; | ||
- if (!file_exists(git_path("MERGE_HEAD"))) | ||
+ if (!file_exists(git_path_merge_head())) | ||
die(_("There is no merge to abort (MERGE_HEAD missing).")); | ||
/* Invoke 'git reset --merge' */ | ||
@@ -1215,7 +1215,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) | ||
if (read_cache_unmerged()) | ||
die_resolve_conflict("merge"); | ||
- if (file_exists(git_path("MERGE_HEAD"))) { | ||
+ if (file_exists(git_path_merge_head())) { | ||
/* | ||
* There is no unmerged entry, don't advise 'git | ||
* add/rm <file>', just 'git commit'. | ||
@@ -1226,7 +1226,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) | ||
else | ||
die(_("You have not concluded your merge (MERGE_HEAD exists).")); | ||
} | ||
- if (file_exists(git_path("CHERRY_PICK_HEAD"))) { | ||
+ if (file_exists(git_path_cherry_pick_head())) { | ||
if (advice_resolve_conflict) | ||
die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" | ||
"Please, commit your changes before you merge.")); | ||
View
49
builtin/notes.c
@@ -19,6 +19,7 @@ | ||
#include "string-list.h" | ||
#include "notes-merge.h" | ||
#include "notes-utils.h" | ||
+#include "branch.h" | ||
static const char * const git_notes_usage[] = { | ||
N_("git notes [--ref <notes-ref>] [list [<object>]]"), | ||
@@ -737,6 +738,19 @@ static int merge_commit(struct notes_merge_options *o) | ||
return ret; | ||
} | ||
+static int git_config_get_notes_strategy(const char *key, | ||
+ enum notes_merge_strategy *strategy) | ||
+{ | ||
+ const char *value; | ||
+ | ||
+ if (git_config_get_string_const(key, &value)) | ||
+ return 1; | ||
+ if (parse_notes_merge_strategy(value, strategy)) | ||
+ git_die_config(key, "unknown notes merge strategy %s", value); | ||
+ | ||
+ return 0; | ||
+} | ||
+ | ||
static int merge(int argc, const char **argv, const char *prefix) | ||
{ | ||
struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT; | ||
@@ -795,24 +809,28 @@ static int merge(int argc, const char **argv, const char *prefix) | ||
expand_notes_ref(&remote_ref); | ||
o.remote_ref = remote_ref.buf; | ||
+ t = init_notes_check("merge"); | ||
+ | ||
if (strategy) { | ||
- if (!strcmp(strategy, "manual")) | ||
- o.strategy = NOTES_MERGE_RESOLVE_MANUAL; | ||
- else if (!strcmp(strategy, "ours")) | ||
- o.strategy = NOTES_MERGE_RESOLVE_OURS; | ||
- else if (!strcmp(strategy, "theirs")) | ||
- o.strategy = NOTES_MERGE_RESOLVE_THEIRS; | ||
- else if (!strcmp(strategy, "union")) | ||
- o.strategy = NOTES_MERGE_RESOLVE_UNION; | ||
- else if (!strcmp(strategy, "cat_sort_uniq")) | ||
- o.strategy = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ; | ||
- else { | ||
+ if (parse_notes_merge_strategy(strategy, &o.strategy)) { | ||
error("Unknown -s/--strategy: %s", strategy); | ||
usage_with_options(git_notes_merge_usage, options); | ||
} | ||
- } | ||
+ } else { | ||
+ struct strbuf merge_key = STRBUF_INIT; | ||
+ const char *short_ref = NULL; | ||
- t = init_notes_check("merge"); | ||
+ if (!skip_prefix(o.local_ref, "refs/notes/", &short_ref)) | ||
+ die("BUG: local ref %s is outside of refs/notes/", | ||
+ o.local_ref); | ||
+ | ||
+ strbuf_addf(&merge_key, "notes.%s.mergeStrategy", short_ref); | ||
+ | ||
+ if (git_config_get_notes_strategy(merge_key.buf, &o.strategy)) | ||
+ git_config_get_notes_strategy("notes.mergeStrategy", &o.strategy); | ||
+ | ||
+ strbuf_release(&merge_key); | ||
+ } | ||
strbuf_addf(&msg, "notes: Merged notes from %s into %s", | ||
remote_ref.buf, default_notes_ref()); | ||
@@ -825,10 +843,15 @@ static int merge(int argc, const char **argv, const char *prefix) | ||
update_ref(msg.buf, default_notes_ref(), result_sha1, NULL, | ||
0, UPDATE_REFS_DIE_ON_ERR); | ||
else { /* Merge has unresolved conflicts */ | ||
+ char *existing; | ||
/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ | ||
update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL, | ||
0, UPDATE_REFS_DIE_ON_ERR); | ||
/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ | ||
+ existing = find_shared_symref("NOTES_MERGE_REF", default_notes_ref()); | ||
+ if (existing) | ||
+ die(_("A notes merge into %s is already in-progress at %s"), | ||
+ default_notes_ref(), existing); | ||
if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) | ||
die("Failed to store link to current notes ref (%s)", | ||
default_notes_ref()); | ||
View
29
builtin/pack-objects.c
@@ -25,8 +25,8 @@ | ||
#include "argv-array.h" | ||
static const char *pack_usage[] = { | ||
- N_("git pack-objects --stdout [options...] [< ref-list | < object-list]"), | ||
- N_("git pack-objects [options...] base-name [< ref-list | < object-list]"), | ||
+ N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"), | ||
+ N_("git pack-objects [<options>...] <base-name> [< <ref-list> | < <object-list>]"), | ||
NULL | ||
}; | ||
@@ -2588,23 +2588,6 @@ static int option_parse_unpack_unreachable(const struct option *opt, | ||
return 0; | ||
} | ||
-static int option_parse_ulong(const struct option *opt, | ||
- const char *arg, int unset) | ||
-{ | ||
- if (unset) | ||
- die(_("option %s does not accept negative form"), | ||
- opt->long_name); | ||
- | ||
- if (!git_parse_ulong(arg, opt->value)) | ||
- die(_("unable to parse value '%s' for option %s"), | ||
- arg, opt->long_name); | ||
- return 0; | ||
-} | ||
- | ||
-#define OPT_ULONG(s, l, v, h) \ | ||
- { OPTION_CALLBACK, (s), (l), (v), "n", (h), \ | ||
- PARSE_OPT_NONEG, option_parse_ulong } | ||
- | ||
int cmd_pack_objects(int argc, const char **argv, const char *prefix) | ||
{ | ||
int use_internal_rev_list = 0; | ||
@@ -2627,16 +2610,16 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) | ||
{ OPTION_CALLBACK, 0, "index-version", NULL, N_("version[,offset]"), | ||
N_("write the pack index file in the specified idx format version"), | ||
0, option_parse_index_version }, | ||
- OPT_ULONG(0, "max-pack-size", &pack_size_limit, | ||
- N_("maximum size of each output pack file")), | ||
+ OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit, | ||
+ N_("maximum size of each output pack file")), | ||
OPT_BOOL(0, "local", &local, | ||
N_("ignore borrowed objects from alternate object store")), | ||
OPT_BOOL(0, "incremental", &incremental, | ||
N_("ignore packed objects")), | ||
OPT_INTEGER(0, "window", &window, | ||
N_("limit pack window by objects")), | ||
- OPT_ULONG(0, "window-memory", &window_memory_limit, | ||
- N_("limit pack window by memory in addition to object limit")), | ||
+ OPT_MAGNITUDE(0, "window-memory", &window_memory_limit, | ||
+ N_("limit pack window by memory in addition to object limit")), | ||
OPT_INTEGER(0, "depth", &depth, | ||
N_("maximum length of delta chain allowed in the resulting pack")), | ||
OPT_BOOL(0, "reuse-delta", &reuse_delta, | ||
View
887
builtin/pull.c
@@ -0,0 +1,887 @@ | ||
+/* | ||
+ * Builtin "git pull" | ||
+ * | ||
+ * Based on git-pull.sh by Junio C Hamano | ||
+ * | ||
+ * Fetch one or more remote refs and merge it/them into the current HEAD. | ||
+ */ | ||
+#include "cache.h" | ||
+#include "builtin.h" | ||
+#include "parse-options.h" | ||
+#include "exec_cmd.h" | ||
+#include "run-command.h" | ||
+#include "sha1-array.h" | ||
+#include "remote.h" | ||
+#include "dir.h" | ||
+#include "refs.h" | ||
+#include "revision.h" | ||
+#include "tempfile.h" | ||
+#include "lockfile.h" | ||
+ | ||
+enum rebase_type { | ||
+ REBASE_INVALID = -1, | ||
+ REBASE_FALSE = 0, | ||
+ REBASE_TRUE, | ||
+ REBASE_PRESERVE | ||
+}; | ||
+ | ||
+/** | ||
+ * Parses the value of --rebase. If value is a false value, returns | ||
+ * REBASE_FALSE. If value is a true value, returns REBASE_TRUE. If value is | ||
+ * "preserve", returns REBASE_PRESERVE. If value is a invalid value, dies with | ||
+ * a fatal error if fatal is true, otherwise returns REBASE_INVALID. | ||
+ */ | ||
+static enum rebase_type parse_config_rebase(const char *key, const char *value, | ||
+ int fatal) | ||
+{ | ||
+ int v = git_config_maybe_bool("pull.rebase", value); | ||
+ | ||
+ if (!v) | ||
+ return REBASE_FALSE; | ||
+ else if (v > 0) | ||
+ return REBASE_TRUE; | ||
+ else if (!strcmp(value, "preserve")) | ||
+ return REBASE_PRESERVE; | ||
+ | ||
+ if (fatal) | ||
+ die(_("Invalid value for %s: %s"), key, value); | ||
+ else | ||
+ error(_("Invalid value for %s: %s"), key, value); | ||
+ | ||
+ return REBASE_INVALID; | ||
+} | ||
+ | ||
+/** | ||
+ * Callback for --rebase, which parses arg with parse_config_rebase(). | ||
+ */ | ||
+static int parse_opt_rebase(const struct option *opt, const char *arg, int unset) | ||
+{ | ||
+ enum rebase_type *value = opt->value; | ||
+ | ||
+ if (arg) | ||
+ *value = parse_config_rebase("--rebase", arg, 0); | ||
+ else | ||
+ *value = unset ? REBASE_FALSE : REBASE_TRUE; | ||
+ return *value == REBASE_INVALID ? -1 : 0; | ||
+} | ||
+ | ||
+static const char * const pull_usage[] = { | ||
+ N_("git pull [options] [<repository> [<refspec>...]]"), | ||
+ NULL | ||
+}; | ||
+ | ||
+/* Shared options */ | ||
+static int opt_verbosity; | ||
+static char *opt_progress; | ||
+ | ||
+/* Options passed to git-merge or git-rebase */ | ||
+static enum rebase_type opt_rebase = -1; | ||
+static char *opt_diffstat; | ||
+static char *opt_log; | ||
+static char *opt_squash; | ||
+static char *opt_commit; | ||
+static char *opt_edit; | ||
+static char *opt_ff; | ||
+static char *opt_verify_signatures; | ||
+static struct argv_array opt_strategies = ARGV_ARRAY_INIT; | ||
+static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT; | ||
+static char *opt_gpg_sign; | ||
+ | ||
+/* Options passed to git-fetch */ | ||
+static char *opt_all; | ||
+static char *opt_append; | ||
+static char *opt_upload_pack; | ||
+static int opt_force; | ||
+static char *opt_tags; | ||
+static char *opt_prune; | ||
+static char *opt_recurse_submodules; | ||
+static int opt_dry_run; | ||
+static char *opt_keep; | ||
+static char *opt_depth; | ||
+static char *opt_unshallow; | ||
+static char *opt_update_shallow; | ||
+static char *opt_refmap; | ||
+ | ||
+static struct option pull_options[] = { | ||
+ /* Shared options */ | ||
+ OPT__VERBOSITY(&opt_verbosity), | ||
+ OPT_PASSTHRU(0, "progress", &opt_progress, NULL, | ||
+ N_("force progress reporting"), | ||
+ PARSE_OPT_NOARG), | ||
+ | ||
+ /* Options passed to git-merge or git-rebase */ | ||
+ OPT_GROUP(N_("Options related to merging")), | ||
+ { OPTION_CALLBACK, 'r', "rebase", &opt_rebase, | ||
+ "false|true|preserve", | ||
+ N_("incorporate changes by rebasing rather than merging"), | ||
+ PARSE_OPT_OPTARG, parse_opt_rebase }, | ||
+ OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL, | ||
+ N_("do not show a diffstat at the end of the merge"), | ||
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG), | ||
+ OPT_PASSTHRU(0, "stat", &opt_diffstat, NULL, | ||
+ N_("show a diffstat at the end of the merge"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "summary", &opt_diffstat, NULL, | ||
+ N_("(synonym to --stat)"), | ||
+ PARSE_OPT_NOARG | PARSE_OPT_HIDDEN), | ||
+ OPT_PASSTHRU(0, "log", &opt_log, N_("n"), | ||
+ N_("add (at most <n>) entries from shortlog to merge commit message"), | ||
+ PARSE_OPT_OPTARG), | ||
+ OPT_PASSTHRU(0, "squash", &opt_squash, NULL, | ||
+ N_("create a single commit instead of doing a merge"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "commit", &opt_commit, NULL, | ||
+ N_("perform a commit if the merge succeeds (default)"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "edit", &opt_edit, NULL, | ||
+ N_("edit message before committing"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "ff", &opt_ff, NULL, | ||
+ N_("allow fast-forward"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "ff-only", &opt_ff, NULL, | ||
+ N_("abort if fast-forward is not possible"), | ||
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG), | ||
+ OPT_PASSTHRU(0, "verify-signatures", &opt_verify_signatures, NULL, | ||
+ N_("verify that the named commit has a valid GPG signature"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"), | ||
+ N_("merge strategy to use"), | ||
+ 0), | ||
+ OPT_PASSTHRU_ARGV('X', "strategy-option", &opt_strategy_opts, | ||
+ N_("option=value"), | ||
+ N_("option for selected merge strategy"), | ||
+ 0), | ||
+ OPT_PASSTHRU('S', "gpg-sign", &opt_gpg_sign, N_("key-id"), | ||
+ N_("GPG sign commit"), | ||
+ PARSE_OPT_OPTARG), | ||
+ | ||
+ /* Options passed to git-fetch */ | ||
+ OPT_GROUP(N_("Options related to fetching")), | ||
+ OPT_PASSTHRU(0, "all", &opt_all, NULL, | ||
+ N_("fetch from all remotes"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU('a', "append", &opt_append, NULL, | ||
+ N_("append to .git/FETCH_HEAD instead of overwriting"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "upload-pack", &opt_upload_pack, N_("path"), | ||
+ N_("path to upload pack on remote end"), | ||
+ 0), | ||
+ OPT__FORCE(&opt_force, N_("force overwrite of local branch")), | ||
+ OPT_PASSTHRU('t', "tags", &opt_tags, NULL, | ||
+ N_("fetch all tags and associated objects"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU('p', "prune", &opt_prune, NULL, | ||
+ N_("prune remote-tracking branches no longer on remote"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "recurse-submodules", &opt_recurse_submodules, | ||
+ N_("on-demand"), | ||
+ N_("control recursive fetching of submodules"), | ||
+ PARSE_OPT_OPTARG), | ||
+ OPT_BOOL(0, "dry-run", &opt_dry_run, | ||
+ N_("dry run")), | ||
+ OPT_PASSTHRU('k', "keep", &opt_keep, NULL, | ||
+ N_("keep downloaded pack"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "depth", &opt_depth, N_("depth"), | ||
+ N_("deepen history of shallow clone"), | ||
+ 0), | ||
+ OPT_PASSTHRU(0, "unshallow", &opt_unshallow, NULL, | ||
+ N_("convert to a complete repository"), | ||
+ PARSE_OPT_NONEG | PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "update-shallow", &opt_update_shallow, NULL, | ||
+ N_("accept refs that update .git/shallow"), | ||
+ PARSE_OPT_NOARG), | ||
+ OPT_PASSTHRU(0, "refmap", &opt_refmap, N_("refmap"), | ||
+ N_("specify fetch refmap"), | ||
+ PARSE_OPT_NONEG), | ||
+ | ||
+ OPT_END() | ||
+}; | ||
+ | ||
+/** | ||
+ * Pushes "-q" or "-v" switches into arr to match the opt_verbosity level. | ||
+ */ | ||
+static void argv_push_verbosity(struct argv_array *arr) | ||
+{ | ||
+ int verbosity; | ||
+ | ||
+ for (verbosity = opt_verbosity; verbosity > 0; verbosity--) | ||
+ argv_array_push(arr, "-v"); | ||
+ | ||
+ for (verbosity = opt_verbosity; verbosity < 0; verbosity++) | ||
+ argv_array_push(arr, "-q"); | ||
+} | ||
+ | ||
+/** | ||
+ * Pushes "-f" switches into arr to match the opt_force level. | ||
+ */ | ||
+static void argv_push_force(struct argv_array *arr) | ||
+{ | ||
+ int force = opt_force; | ||
+ while (force-- > 0) | ||
+ argv_array_push(arr, "-f"); | ||
+} | ||
+ | ||
+/** | ||
+ * Sets the GIT_REFLOG_ACTION environment variable to the concatenation of argv | ||
+ */ | ||
+static void set_reflog_message(int argc, const char **argv) | ||
+{ | ||
+ int i; | ||
+ struct strbuf msg = STRBUF_INIT; | ||
+ | ||
+ for (i = 0; i < argc; i++) { | ||
+ if (i) | ||
+ strbuf_addch(&msg, ' '); | ||
+ strbuf_addstr(&msg, argv[i]); | ||
+ } | ||
+ | ||
+ setenv("GIT_REFLOG_ACTION", msg.buf, 0); | ||
+ | ||
+ strbuf_release(&msg); | ||
+} | ||
+ | ||
+/** | ||
+ * If pull.ff is unset, returns NULL. If pull.ff is "true", returns "--ff". If | ||
+ * pull.ff is "false", returns "--no-ff". If pull.ff is "only", returns | ||
+ * "--ff-only". Otherwise, if pull.ff is set to an invalid value, die with an | ||
+ * error. | ||
+ */ | ||
+static const char *config_get_ff(void) | ||
+{ | ||
+ const char *value; | ||
+ | ||
+ if (git_config_get_value("pull.ff", &value)) | ||
+ return NULL; | ||
+ | ||
+ switch (git_config_maybe_bool("pull.ff", value)) { | ||
+ case 0: | ||
+ return "--no-ff"; | ||
+ case 1: | ||
+ return "--ff"; | ||
+ } | ||
+ | ||
+ if (!strcmp(value, "only")) | ||
+ return "--ff-only"; | ||
+ | ||
+ die(_("Invalid value for pull.ff: %s"), value); | ||
+} | ||
+ | ||
+/** | ||
+ * Returns the default configured value for --rebase. It first looks for the | ||
+ * value of "branch.$curr_branch.rebase", where $curr_branch is the current | ||
+ * branch, and if HEAD is detached or the configuration key does not exist, | ||
+ * looks for the value of "pull.rebase". If both configuration keys do not | ||
+ * exist, returns REBASE_FALSE. | ||
+ */ | ||
+static enum rebase_type config_get_rebase(void) | ||
+{ | ||
+ struct branch *curr_branch = branch_get("HEAD"); | ||
+ const char *value; | ||
+ | ||
+ if (curr_branch) { | ||
+ char *key = xstrfmt("branch.%s.rebase", curr_branch->name); | ||
+ | ||
+ if (!git_config_get_value(key, &value)) { | ||
+ enum rebase_type ret = parse_config_rebase(key, value, 1); | ||
+ free(key); | ||
+ return ret; | ||
+ } | ||
+ | ||
+ free(key); | ||
+ } | ||
+ | ||
+ if (!git_config_get_value("pull.rebase", &value)) | ||
+ return parse_config_rebase("pull.rebase", value, 1); | ||
+ | ||
+ return REBASE_FALSE; | ||
+} | ||
+ | ||
+/** | ||
+ * Returns 1 if there are unstaged changes, 0 otherwise. | ||
+ */ | ||
+static int has_unstaged_changes(const char *prefix) | ||
+{ | ||
+ struct rev_info rev_info; | ||
+ int result; | ||
+ | ||
+ init_revisions(&rev_info, prefix); | ||
+ DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES); | ||
+ DIFF_OPT_SET(&rev_info.diffopt, QUICK); | ||
+ diff_setup_done(&rev_info.diffopt); | ||
+ result = run_diff_files(&rev_info, 0); | ||
+ return diff_result_code(&rev_info.diffopt, result); | ||
+} | ||
+ | ||
+/** | ||
+ * Returns 1 if there are uncommitted changes, 0 otherwise. | ||
+ */ | ||
+static int has_uncommitted_changes(const char *prefix) | ||
+{ | ||
+ struct rev_info rev_info; | ||
+ int result; | ||
+ | ||
+ if (is_cache_unborn()) | ||
+ return 0; | ||
+ | ||
+ init_revisions(&rev_info, prefix); | ||
+ DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES); | ||
+ DIFF_OPT_SET(&rev_info.diffopt, QUICK); | ||
+ add_head_to_pending(&rev_info); | ||
+ diff_setup_done(&rev_info.diffopt); | ||
+ result = run_diff_index(&rev_info, 1); | ||
+ return diff_result_code(&rev_info.diffopt, result); | ||
+} | ||
+ | ||
+/** | ||
+ * If the work tree has unstaged or uncommitted changes, dies with the | ||
+ * appropriate message. | ||
+ */ | ||
+static void die_on_unclean_work_tree(const char *prefix) | ||
+{ | ||
+ struct lock_file *lock_file = xcalloc(1, sizeof(*lock_file)); | ||
+ int do_die = 0; | ||
+ | ||
+ hold_locked_index(lock_file, 0); | ||
+ refresh_cache(REFRESH_QUIET); | ||
+ update_index_if_able(&the_index, lock_file); | ||
+ rollback_lock_file(lock_file); | ||
+ | ||
+ if (has_unstaged_changes(prefix)) { | ||
+ error(_("Cannot pull with rebase: You have unstaged changes.")); | ||
+ do_die = 1; | ||
+ } | ||
+ | ||
+ if (has_uncommitted_changes(prefix)) { | ||
+ if (do_die) | ||
+ error(_("Additionally, your index contains uncommitted changes.")); | ||
+ else | ||
+ error(_("Cannot pull with rebase: Your index contains uncommitted changes.")); | ||
+ do_die = 1; | ||
+ } | ||
+ | ||
+ if (do_die) | ||
+ exit(1); | ||
+} | ||
+ | ||
+/** | ||
+ * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge | ||
+ * into merge_heads. | ||
+ */ | ||
+static void get_merge_heads(struct sha1_array *merge_heads) | ||
+{ | ||
+ const char *filename = git_path("FETCH_HEAD"); | ||
+ FILE *fp; | ||
+ struct strbuf sb = STRBUF_INIT; | ||
+ unsigned char sha1[GIT_SHA1_RAWSZ]; | ||
+ | ||
+ if (!(fp = fopen(filename, "r"))) | ||
+ die_errno(_("could not open '%s' for reading"), filename); | ||
+ while (strbuf_getline(&sb, fp, '\n') != EOF) { | ||
+ if (get_sha1_hex(sb.buf, sha1)) | ||
+ continue; /* invalid line: does not start with SHA1 */ | ||
+ if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t")) | ||
+ continue; /* ref is not-for-merge */ | ||
+ sha1_array_append(merge_heads, sha1); | ||
+ } | ||
+ fclose(fp); | ||
+ strbuf_release(&sb); | ||
+} | ||
+ | ||
+/** | ||
+ * Used by die_no_merge_candidates() as a for_each_remote() callback to | ||
+ * retrieve the name of the remote if the repository only has one remote. | ||
+ */ | ||
+static int get_only_remote(struct remote *remote, void *cb_data) | ||
+{ | ||
+ const char **remote_name = cb_data; | ||
+ | ||
+ if (*remote_name) | ||
+ return -1; | ||
+ | ||
+ *remote_name = remote->name; | ||
+ return 0; | ||
+} | ||
+ | ||
+/** | ||
+ * Dies with the appropriate reason for why there are no merge candidates: | ||
+ * | ||
+ * 1. We fetched from a specific remote, and a refspec was given, but it ended | ||
+ * up not fetching anything. This is usually because the user provided a | ||
+ * wildcard refspec which had no matches on the remote end. | ||
+ * | ||
+ * 2. We fetched from a non-default remote, but didn't specify a branch to | ||
+ * merge. We can't use the configured one because it applies to the default | ||
+ * remote, thus the user must specify the branches to merge. | ||
+ * | ||
+ * 3. We fetched from the branch's or repo's default remote, but: | ||
+ * | ||
+ * a. We are not on a branch, so there will never be a configured branch to | ||
+ * merge with. | ||
+ * | ||
+ * b. We are on a branch, but there is no configured branch to merge with. | ||
+ * | ||
+ * 4. We fetched from the branch's or repo's default remote, but the configured | ||
+ * branch to merge didn't get fetched. (Either it doesn't exist, or wasn't | ||
+ * part of the configured fetch refspec.) | ||
+ */ | ||
+static void NORETURN die_no_merge_candidates(const char *repo, const char **refspecs) | ||
+{ | ||
+ struct branch *curr_branch = branch_get("HEAD"); | ||
+ const char *remote = curr_branch ? curr_branch->remote_name : NULL; | ||
+ | ||
+ if (*refspecs) { | ||
+ if (opt_rebase) | ||
+ fprintf_ln(stderr, _("There is no candidate for rebasing against among the refs that you just fetched.")); | ||
+ else | ||
+ fprintf_ln(stderr, _("There are no candidates for merging among the refs that you just fetched.")); | ||
+ fprintf_ln(stderr, _("Generally this means that you provided a wildcard refspec which had no\n" | ||
+ "matches on the remote end.")); | ||
+ } else if (repo && curr_branch && (!remote || strcmp(repo, remote))) { | ||
+ fprintf_ln(stderr, _("You asked to pull from the remote '%s', but did not specify\n" | ||
+ "a branch. Because this is not the default configured remote\n" | ||
+ "for your current branch, you must specify a branch on the command line."), | ||
+ repo); | ||
+ } else if (!curr_branch) { | ||
+ fprintf_ln(stderr, _("You are not currently on a branch.")); | ||
+ if (opt_rebase) | ||
+ fprintf_ln(stderr, _("Please specify which branch you want to rebase against.")); | ||
+ else | ||
+ fprintf_ln(stderr, _("Please specify which branch you want to merge with.")); | ||
+ fprintf_ln(stderr, _("See git-pull(1) for details.")); | ||
+ fprintf(stderr, "\n"); | ||
+ fprintf_ln(stderr, " git pull <remote> <branch>"); | ||
+ fprintf(stderr, "\n"); | ||
+ } else if (!curr_branch->merge_nr) { | ||
+ const char *remote_name = NULL; | ||
+ | ||
+ if (for_each_remote(get_only_remote, &remote_name) || !remote_name) | ||
+ remote_name = "<remote>"; | ||
+ | ||
+ fprintf_ln(stderr, _("There is no tracking information for the current branch.")); | ||
+ if (opt_rebase) | ||
+ fprintf_ln(stderr, _("Please specify which branch you want to rebase against.")); | ||
+ else | ||
+ fprintf_ln(stderr, _("Please specify which branch you want to merge with.")); | ||
+ fprintf_ln(stderr, _("See git-pull(1) for details.")); | ||
+ fprintf(stderr, "\n"); | ||
+ fprintf_ln(stderr, " git pull <remote> <branch>"); | ||
+ fprintf(stderr, "\n"); | ||
+ fprintf_ln(stderr, _("If you wish to set tracking information for this branch you can do so with:\n" | ||
+ "\n" | ||
+ " git branch --set-upstream-to=%s/<branch> %s\n"), | ||
+ remote_name, curr_branch->name); | ||
+ } else | ||
+ fprintf_ln(stderr, _("Your configuration specifies to merge with the ref '%s'\n" | ||
+ "from the remote, but no such ref was fetched."), | ||
+ *curr_branch->merge_name); | ||
+ exit(1); | ||
+} | ||
+ | ||
+/** | ||
+ * Parses argv into [<repo> [<refspecs>...]], returning their values in `repo` | ||
+ * as a string and `refspecs` as a null-terminated array of strings. If `repo` | ||
+ * is not provided in argv, it is set to NULL. | ||
+ */ | ||
+static void parse_repo_refspecs(int argc, const char **argv, const char **repo, | ||
+ const char ***refspecs) | ||
+{ | ||
+ if (argc > 0) { | ||
+ *repo = *argv++; | ||
+ argc--; | ||
+ } else | ||
+ *repo = NULL; | ||
+ *refspecs = argv; | ||
+} | ||
+ | ||
+/** | ||
+ * Runs git-fetch, returning its exit status. `repo` and `refspecs` are the | ||
+ * repository and refspecs to fetch, or NULL if they are not provided. | ||
+ */ | ||
+static int run_fetch(const char *repo, const char **refspecs) | ||
+{ | ||
+ struct argv_array args = ARGV_ARRAY_INIT; | ||
+ int ret; | ||
+ | ||
+ argv_array_pushl(&args, "fetch", "--update-head-ok", NULL); | ||
+ | ||
+ /* Shared options */ | ||
+ argv_push_verbosity(&args); | ||
+ if (opt_progress) | ||
+ argv_array_push(&args, opt_progress); | ||
+ | ||
+ /* Options passed to git-fetch */ | ||
+ if (opt_all) | ||
+ argv_array_push(&args, opt_all); | ||
+ if (opt_append) | ||
+ argv_array_push(&args, opt_append); | ||
+ if (opt_upload_pack) | ||
+ argv_array_push(&args, opt_upload_pack); | ||
+ argv_push_force(&args); | ||
+ if (opt_tags) | ||
+ argv_array_push(&args, opt_tags); | ||
+ if (opt_prune) | ||
+ argv_array_push(&args, opt_prune); | ||
+ if (opt_recurse_submodules) | ||
+ argv_array_push(&args, opt_recurse_submodules); | ||
+ if (opt_dry_run) | ||
+ argv_array_push(&args, "--dry-run"); | ||
+ if (opt_keep) | ||
+ argv_array_push(&args, opt_keep); | ||
+ if (opt_depth) | ||
+ argv_array_push(&args, opt_depth); | ||
+ if (opt_unshallow) | ||
+ argv_array_push(&args, opt_unshallow); | ||
+ if (opt_update_shallow) | ||
+ argv_array_push(&args, opt_update_shallow); | ||
+ if (opt_refmap) | ||
+ argv_array_push(&args, opt_refmap); | ||
+ | ||
+ if (repo) { | ||
+ argv_array_push(&args, repo); | ||
+ argv_array_pushv(&args, refspecs); | ||
+ } else if (*refspecs) | ||
+ die("BUG: refspecs without repo?"); | ||
+ ret = run_command_v_opt(args.argv, RUN_GIT_CMD); | ||
+ argv_array_clear(&args); | ||
+ return ret; | ||
+} | ||
+ | ||
+/** | ||
+ * "Pulls into void" by branching off merge_head. | ||
+ */ | ||
+static int pull_into_void(const unsigned char *merge_head, | ||
+ const unsigned char *curr_head) | ||
+{ | ||
+ /* | ||
+ * Two-way merge: we treat the index as based on an empty tree, | ||
+ * and try to fast-forward to HEAD. This ensures we will not lose | ||
+ * index/worktree changes that the user already made on the unborn | ||
+ * branch. | ||
+ */ | ||
+ if (checkout_fast_forward(EMPTY_TREE_SHA1_BIN, merge_head, 0)) | ||
+ return 1; | ||
+ | ||
+ if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR)) | ||
+ return 1; | ||
+ | ||
+ return 0; | ||
+} | ||
+ | ||
+/** | ||
+ * Runs git-merge, returning its exit status. | ||
+ */ | ||
+static int run_merge(void) | ||
+{ | ||
+ int ret; | ||
+ struct argv_array args = ARGV_ARRAY_INIT; | ||
+ | ||
+ argv_array_pushl(&args, "merge", NULL); | ||
+ | ||
+ /* Shared options */ | ||
+ argv_push_verbosity(&args); | ||
+ if (opt_progress) | ||
+ argv_array_push(&args, opt_progress); | ||
+ | ||
+ /* Options passed to git-merge */ | ||
+ if (opt_diffstat) | ||
+ argv_array_push(&args, opt_diffstat); | ||
+ if (opt_log) | ||
+ argv_array_push(&args, opt_log); | ||
+ if (opt_squash) | ||
+ argv_array_push(&args, opt_squash); | ||
+ if (opt_commit) | ||
+ argv_array_push(&args, opt_commit); | ||
+ if (opt_edit) | ||
+ argv_array_push(&args, opt_edit); | ||
+ if (opt_ff) | ||
+ argv_array_push(&args, opt_ff); | ||
+ if (opt_verify_signatures) | ||
+ argv_array_push(&args, opt_verify_signatures); | ||
+ argv_array_pushv(&args, opt_strategies.argv); | ||
+ argv_array_pushv(&args, opt_strategy_opts.argv); | ||
+ if (opt_gpg_sign) | ||
+ argv_array_push(&args, opt_gpg_sign); | ||
+ | ||
+ argv_array_push(&args, "FETCH_HEAD"); | ||
+ ret = run_command_v_opt(args.argv, RUN_GIT_CMD); | ||
+ argv_array_clear(&args); | ||
+ return ret; | ||
+} | ||
+ | ||
+/** | ||
+ * Returns remote's upstream branch for the current branch. If remote is NULL, | ||
+ * the current branch's configured default remote is used. Returns NULL if | ||
+ * `remote` does not name a valid remote, HEAD does not point to a branch, | ||
+ * remote is not the branch's configured remote or the branch does not have any | ||
+ * configured upstream branch. | ||
+ */ | ||
+static const char *get_upstream_branch(const char *remote) | ||
+{ | ||
+ struct remote *rm; | ||
+ struct branch *curr_branch; | ||
+ const char *curr_branch_remote; | ||
+ | ||
+ rm = remote_get(remote); | ||
+ if (!rm) | ||
+ return NULL; | ||
+ | ||
+ curr_branch = branch_get("HEAD"); | ||
+ if (!curr_branch) | ||
+ return NULL; | ||
+ | ||
+ curr_branch_remote = remote_for_branch(curr_branch, NULL); | ||
+ assert(curr_branch_remote); | ||
+ | ||
+ if (strcmp(curr_branch_remote, rm->name)) | ||
+ return NULL; | ||
+ | ||
+ return branch_get_upstream(curr_branch, NULL); | ||
+} | ||
+ | ||
+/** | ||
+ * Derives the remote tracking branch from the remote and refspec. | ||
+ * | ||
+ * FIXME: The current implementation assumes the default mapping of | ||
+ * refs/heads/<branch_name> to refs/remotes/<remote_name>/<branch_name>. | ||
+ */ | ||
+static const char *get_tracking_branch(const char *remote, const char *refspec) | ||
+{ | ||
+ struct refspec *spec; | ||
+ const char *spec_src; | ||
+ const char *merge_branch; | ||
+ | ||
+ spec = parse_fetch_refspec(1, &refspec); | ||
+ spec_src = spec->src; | ||
+ if (!*spec_src || !strcmp(spec_src, "HEAD")) | ||
+ spec_src = "HEAD"; | ||
+ else if (skip_prefix(spec_src, "heads/", &spec_src)) | ||
+ ; | ||
+ else if (skip_prefix(spec_src, "refs/heads/", &spec_src)) | ||
+ ; | ||
+ else if (starts_with(spec_src, "refs/") || | ||
+ starts_with(spec_src, "tags/") || | ||
+ starts_with(spec_src, "remotes/")) | ||
+ spec_src = ""; | ||
+ | ||
+ if (*spec_src) { | ||
+ if (!strcmp(remote, ".")) | ||
+ merge_branch = mkpath("refs/heads/%s", spec_src); | ||
+ else | ||
+ merge_branch = mkpath("refs/remotes/%s/%s", remote, spec_src); | ||
+ } else | ||
+ merge_branch = NULL; | ||
+ | ||
+ free_refspec(1, spec); | ||
+ return merge_branch; | ||
+} | ||
+ | ||
+/** | ||
+ * Given the repo and refspecs, sets fork_point to the point at which the | ||
+ * current branch forked from its remote tracking branch. Returns 0 on success, | ||
+ * -1 on failure. | ||
+ */ | ||
+static int get_rebase_fork_point(unsigned char *fork_point, const char *repo, | ||
+ const char *refspec) | ||
+{ | ||
+ int ret; | ||
+ struct branch *curr_branch; | ||
+ const char *remote_branch; | ||
+ struct child_process cp = CHILD_PROCESS_INIT; | ||
+ struct strbuf sb = STRBUF_INIT; | ||
+ | ||
+ curr_branch = branch_get("HEAD"); | ||
+ if (!curr_branch) | ||
+ return -1; | ||
+ | ||
+ if (refspec) | ||
+ remote_branch = get_tracking_branch(repo, refspec); | ||
+ else | ||
+ remote_branch = get_upstream_branch(repo); | ||
+ | ||
+ if (!remote_branch) | ||
+ return -1; | ||
+ | ||
+ argv_array_pushl(&cp.args, "merge-base", "--fork-point", | ||
+ remote_branch, curr_branch->name, NULL); | ||
+ cp.no_stdin = 1; | ||
+ cp.no_stderr = 1; | ||
+ cp.git_cmd = 1; | ||
+ | ||
+ ret = capture_command(&cp, &sb, GIT_SHA1_HEXSZ); | ||
+ if (ret) | ||
+ goto cleanup; | ||
+ | ||
+ ret = get_sha1_hex(sb.buf, fork_point); | ||
+ if (ret) | ||
+ goto cleanup; | ||
+ | ||
+cleanup: | ||
+ strbuf_release(&sb); | ||
+ return ret ? -1 : 0; | ||
+} | ||
+ | ||
+/** | ||
+ * Sets merge_base to the octopus merge base of curr_head, merge_head and | ||
+ * fork_point. Returns 0 if a merge base is found, 1 otherwise. | ||
+ */ | ||
+static int get_octopus_merge_base(unsigned char *merge_base, | ||
+ const unsigned char *curr_head, | ||
+ const unsigned char *merge_head, | ||
+ const unsigned char *fork_point) | ||
+{ | ||
+ struct commit_list *revs = NULL, *result; | ||
+ | ||
+ commit_list_insert(lookup_commit_reference(curr_head), &revs); | ||
+ commit_list_insert(lookup_commit_reference(merge_head), &revs); | ||
+ if (!is_null_sha1(fork_point)) | ||
+ commit_list_insert(lookup_commit_reference(fork_point), &revs); | ||
+ | ||
+ result = reduce_heads(get_octopus_merge_bases(revs)); | ||
+ free_commit_list(revs); | ||
+ if (!result) | ||
+ return 1; | ||
+ | ||
+ hashcpy(merge_base, result->item->object.sha1); | ||
+ return 0; | ||
+} | ||
+ | ||
+/** | ||
+ * Given the current HEAD SHA1, the merge head returned from git-fetch and the | ||
+ * fork point calculated by get_rebase_fork_point(), runs git-rebase with the | ||
+ * appropriate arguments and returns its exit status. | ||
+ */ | ||
+static int run_rebase(const unsigned char *curr_head, | ||
+ const unsigned char *merge_head, | ||
+ const unsigned char *fork_point) | ||
+{ | ||
+ int ret; | ||
+ unsigned char oct_merge_base[GIT_SHA1_RAWSZ]; | ||
+ struct argv_array args = ARGV_ARRAY_INIT; | ||
+ | ||
+ if (!get_octopus_merge_base(oct_merge_base, curr_head, merge_head, fork_point)) | ||
+ if (!is_null_sha1(fork_point) && !hashcmp(oct_merge_base, fork_point)) | ||
+ fork_point = NULL; | ||
+ | ||
+ argv_array_push(&args, "rebase"); | ||
+ | ||
+ /* Shared options */ | ||
+ argv_push_verbosity(&args); | ||
+ | ||
+ /* Options passed to git-rebase */ | ||
+ if (opt_rebase == REBASE_PRESERVE) | ||
+ argv_array_push(&args, "--preserve-merges"); | ||
+ if (opt_diffstat) | ||
+ argv_array_push(&args, opt_diffstat); | ||
+ argv_array_pushv(&args, opt_strategies.argv); | ||
+ argv_array_pushv(&args, opt_strategy_opts.argv); | ||
+ if (opt_gpg_sign) | ||
+ argv_array_push(&args, opt_gpg_sign); | ||
+ | ||
+ argv_array_push(&args, "--onto"); | ||
+ argv_array_push(&args, sha1_to_hex(merge_head)); | ||
+ | ||
+ if (fork_point && !is_null_sha1(fork_point)) | ||
+ argv_array_push(&args, sha1_to_hex(fork_point)); | ||
+ else | ||
+ argv_array_push(&args, sha1_to_hex(merge_head)); | ||
+ | ||
+ ret = run_command_v_opt(args.argv, RUN_GIT_CMD); | ||
+ argv_array_clear(&args); | ||
+ return ret; | ||
+} | ||
+ | ||
+int cmd_pull(int argc, const char **argv, const char *prefix) | ||
+{ | ||
+ const char *repo, **refspecs; | ||
+ struct sha1_array merge_heads = SHA1_ARRAY_INIT; | ||
+ unsigned char orig_head[GIT_SHA1_RAWSZ], curr_head[GIT_SHA1_RAWSZ]; | ||
+ unsigned char rebase_fork_point[GIT_SHA1_RAWSZ]; | ||
+ | ||
+ if (!getenv("GIT_REFLOG_ACTION")) | ||
+ set_reflog_message(argc, argv); | ||
+ | ||
+ argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0); | ||
+ | ||
+ parse_repo_refspecs(argc, argv, &repo, &refspecs); | ||
+ | ||
+ if (!opt_ff) | ||
+ opt_ff = xstrdup_or_null(config_get_ff()); | ||
+ | ||
+ if (opt_rebase < 0) | ||
+ opt_rebase = config_get_rebase(); | ||
+ | ||
+ git_config(git_default_config, NULL); | ||
+ | ||
+ if (read_cache_unmerged()) | ||
+ die_resolve_conflict("Pull"); | ||
+ | ||
+ if (file_exists(git_path("MERGE_HEAD"))) | ||
+ die_conclude_merge(); | ||
+ | ||
+ if (get_sha1("HEAD", orig_head)) | ||
+ hashclr(orig_head); | ||
+ | ||
+ if (opt_rebase) { | ||
+ int autostash = 0; | ||
+ | ||
+ if (is_null_sha1(orig_head) && !is_cache_unborn()) | ||
+ die(_("Updating an unborn branch with changes added to the index.")); | ||
+ | ||
+ git_config_get_bool("rebase.autostash", &autostash); | ||
+ if (!autostash) | ||
+ die_on_unclean_work_tree(prefix); | ||
+ | ||
+ if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs)) | ||
+ hashclr(rebase_fork_point); | ||
+ } | ||
+ | ||
+ if (run_fetch(repo, refspecs)) | ||
+ return 1; | ||
+ | ||
+ if (opt_dry_run) | ||
+ return 0; | ||
+ | ||
+ if (get_sha1("HEAD", curr_head)) | ||
+ hashclr(curr_head); | ||
+ | ||
+ if (!is_null_sha1(orig_head) && !is_null_sha1(curr_head) && | ||
+ hashcmp(orig_head, curr_head)) { | ||
+ /* | ||
+ * The fetch involved updating the current branch. | ||
+ * | ||
+ * The working tree and the index file are still based on | ||
+ * orig_head commit, but we are merging into curr_head. | ||
+ * Update the working tree to match curr_head. | ||
+ */ | ||
+ | ||
+ warning(_("fetch updated the current branch head.\n" | ||
+ "fast-forwarding your working tree from\n" | ||
+ "commit %s."), sha1_to_hex(orig_head)); | ||
+ | ||
+ if (checkout_fast_forward(orig_head, curr_head, 0)) | ||
+ die(_("Cannot fast-forward your working tree.\n" | ||
+ "After making sure that you saved anything precious from\n" | ||
+ "$ git diff %s\n" | ||
+ "output, run\n" | ||
+ "$ git reset --hard\n" | ||
+ "to recover."), sha1_to_hex(orig_head)); | ||
+ } | ||
+ | ||
+ get_merge_heads(&merge_heads); | ||
+ | ||
+ if (!merge_heads.nr) | ||
+ die_no_merge_candidates(repo, refspecs); | ||
+ | ||
+ if (is_null_sha1(orig_head)) { | ||
+ if (merge_heads.nr > 1) | ||
+ die(_("Cannot merge multiple branches into empty head.")); | ||
+ return pull_into_void(*merge_heads.sha1, curr_head); | ||
+ } else if (opt_rebase) { | ||
+ if (merge_heads.nr > 1) | ||
+ die(_("Cannot rebase onto multiple branches.")); | ||
+ return run_rebase(curr_head, *merge_heads.sha1, rebase_fork_point); | ||
+ } else | ||
+ return run_merge(); | ||
+} |
View
42
builtin/push.c
@@ -9,6 +9,7 @@ | ||
#include "transport.h" | ||
#include "parse-options.h" | ||
#include "submodule.h" | ||
+#include "send-pack.h" | ||
static const char * const push_usage[] = { | ||
N_("git push [<options>] [<repository> [<refspec>...]]"), | ||
@@ -471,6 +472,24 @@ static int option_parse_recurse_submodules(const struct option *opt, | ||
return 0; | ||
} | ||
+static void set_push_cert_flags(int *flags, int v) | ||
+{ | ||
+ switch (v) { | ||
+ case SEND_PACK_PUSH_CERT_NEVER: | ||
+ *flags &= ~(TRANSPORT_PUSH_CERT_ALWAYS | TRANSPORT_PUSH_CERT_IF_ASKED); | ||
+ break; | ||
+ case SEND_PACK_PUSH_CERT_ALWAYS: | ||
+ *flags |= TRANSPORT_PUSH_CERT_ALWAYS; | ||
+ *flags &= ~TRANSPORT_PUSH_CERT_IF_ASKED; | ||
+ break; | ||
+ case SEND_PACK_PUSH_CERT_IF_ASKED: | ||
+ *flags |= TRANSPORT_PUSH_CERT_IF_ASKED; | ||
+ *flags &= ~TRANSPORT_PUSH_CERT_ALWAYS; | ||
+ break; | ||
+ } | ||
+} | ||
+ | ||
+ | ||
static int git_push_config(const char *k, const char *v, void *cb) | ||
{ | ||
int *flags = cb; | ||
@@ -486,6 +505,23 @@ static int git_push_config(const char *k, const char *v, void *cb) | ||
else | ||
*flags &= ~TRANSPORT_PUSH_FOLLOW_TAGS; | ||
return 0; | ||
+ } else if (!strcmp(k, "push.gpgsign")) { | ||
+ const char *value; | ||
+ if (!git_config_get_value("push.gpgsign", &value)) { | ||
+ switch (git_config_maybe_bool("push.gpgsign", value)) { | ||
+ case 0: | ||
+ set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_NEVER); | ||
+ break; | ||
+ case 1: | ||
+ set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_ALWAYS); | ||
+ break; | ||
+ default: | ||
+ if (value && !strcasecmp(value, "if-asked")) | ||
+ set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED); | ||
+ else | ||
+ return error("Invalid value for '%s'", k); | ||
+ } | ||
+ } | ||
} | ||
return git_default_config(k, v, NULL); | ||
@@ -495,6 +531,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) | ||
{ | ||
int flags = 0; | ||
int tags = 0; | ||
+ int push_cert = -1; | ||
int rc; | ||
const char *repo = NULL; /* default repository */ | ||
struct option options[] = { | ||
@@ -526,7 +563,9 @@ int cmd_push(int argc, const char **argv, const char *prefix) | ||
OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK), | ||
OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"), | ||
TRANSPORT_PUSH_FOLLOW_TAGS), | ||
- OPT_BIT(0, "signed", &flags, N_("GPG sign the push"), TRANSPORT_PUSH_CERT), | ||
+ { OPTION_CALLBACK, | ||
+ 0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"), | ||
+ PARSE_OPT_OPTARG, option_parse_push_signed }, | ||
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC), | ||
OPT_END() | ||
}; | ||
@@ -534,6 +573,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) | ||
packet_trace_identity("push"); | ||
git_config(git_push_config, &flags); | ||
argc = parse_options(argc, argv, prefix, options, push_usage, 0); | ||
+ set_push_cert_flags(&flags, push_cert); | ||
if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR)))) | ||
die(_("--delete is incompatible with --all, --mirror and --tags")); | ||
View
2
builtin/read-tree.c
@@ -34,7 +34,7 @@ static int list_tree(unsigned char *sha1) | ||
} | ||
static const char * const read_tree_usage[] = { | ||
- N_("git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"), | ||
+ N_("git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>) [-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"), | ||
NULL | ||
}; | ||
View
30
builtin/receive-pack.c
@@ -19,6 +19,7 @@ | ||
#include "tag.h" | ||
#include "gpg-interface.h" | ||
#include "sigchain.h" | ||
+#include "fsck.h" | ||
static const char receive_pack_usage[] = "git receive-pack <git-dir>"; | ||
@@ -36,6 +37,7 @@ static enum deny_action deny_current_branch = DENY_UNCONFIGURED; | ||
static enum deny_action deny_delete_current = DENY_UNCONFIGURED; | ||
static int receive_fsck_objects = -1; | ||
static int transfer_fsck_objects = -1; | ||
+static struct strbuf fsck_msg_types = STRBUF_INIT; | ||
static int receive_unpack_limit = -1; | ||
static int transfer_unpack_limit = -1; | ||
static int advertise_atomic_push = 1; | ||
@@ -115,6 +117,26 @@ static int receive_pack_config(const char *var, const char *value, void *cb) | ||
return 0; | ||
} | ||
+ if (strcmp(var, "receive.fsck.skiplist") == 0) { | ||
+ const char *path; | ||
+ | ||
+ if (git_config_pathname(&path, var, value)) | ||
+ return 1; | ||
+ strbuf_addf(&fsck_msg_types, "%cskiplist=%s", | ||
+ fsck_msg_types.len ? ',' : '=', path); | ||
+ free((char *)path); | ||
+ return 0; | ||
+ } | ||
+ | ||
+ if (skip_prefix(var, "receive.fsck.", &var)) { | ||
+ if (is_valid_msg_type(var, value)) | ||
+ strbuf_addf(&fsck_msg_types, "%c%s=%s", | ||
+ fsck_msg_types.len ? ',' : '=', var, value); | ||
+ else | ||
+ warning("Skipping unknown msg id '%s'", var); | ||
+ return 0; | ||
+ } | ||
+ | ||
if (strcmp(var, "receive.fsckobjects") == 0) { | ||
receive_fsck_objects = git_config_bool(var, value); | ||
return 0; | ||
@@ -911,7 +933,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) | ||
return "deletion prohibited"; | ||
} | ||
- if (!strcmp(namespaced_name, head_name)) { | ||
+ if (head_name && !strcmp(namespaced_name, head_name)) { | ||
switch (deny_delete_current) { | ||
case DENY_IGNORE: | ||
break; | ||
@@ -1490,7 +1512,8 @@ static const char *unpack(int err_fd, struct shallow_info *si) | ||
if (quiet) | ||
argv_array_push(&child.args, "-q"); | ||
if (fsck_objects) | ||
- argv_array_push(&child.args, "--strict"); | ||
+ argv_array_pushf(&child.args, "--strict%s", | ||
+ fsck_msg_types.buf); | ||
child.no_stdout = 1; | ||
child.err = err_fd; | ||
child.git_cmd = 1; | ||
@@ -1508,7 +1531,8 @@ static const char *unpack(int err_fd, struct shallow_info *si) | ||
argv_array_pushl(&child.args, "index-pack", | ||
"--stdin", hdr_arg, keep_arg, NULL); | ||
if (fsck_objects) | ||
- argv_array_push(&child.args, "--strict"); | ||
+ argv_array_pushf(&child.args, "--strict%s", | ||
+ fsck_msg_types.buf); | ||
if (fix_thin) | ||
argv_array_push(&child.args, "--fix-thin"); | ||
child.out = -1; | ||
View
35
builtin/reflog.c
@@ -13,6 +13,8 @@ static const char reflog_expire_usage[] = | ||
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>..."; | ||
static const char reflog_delete_usage[] = | ||
"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>..."; | ||
+static const char reflog_exists_usage[] = | ||
+"git reflog exists <ref>"; | ||
static unsigned long default_reflog_expire; | ||
static unsigned long default_reflog_expire_unreachable; | ||
@@ -427,7 +429,7 @@ static int parse_expire_cfg_value(const char *var, const char *value, unsigned l | ||
if (!value) | ||
return config_error_nonbool(var); | ||
if (parse_expiry_date(value, expire)) | ||
- return error(_("%s' for '%s' is not a valid timestamp"), | ||
+ return error(_("'%s' for '%s' is not a valid timestamp"), | ||
value, var); | ||
return 0; | ||
} | ||
@@ -699,12 +701,38 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) | ||
return status; | ||
} | ||
+static int cmd_reflog_exists(int argc, const char **argv, const char *prefix) | ||
+{ | ||
+ int i, start = 0; | ||
+ | ||
+ for (i = 1; i < argc; i++) { | ||
+ const char *arg = argv[i]; | ||
+ if (!strcmp(arg, "--")) { | ||
+ i++; | ||
+ break; | ||
+ } | ||
+ else if (arg[0] == '-') | ||
+ usage(reflog_exists_usage); | ||
+ else | ||
+ break; | ||
+ } | ||
+ | ||
+ start = i; | ||
+ | ||
+ if (argc - start != 1) | ||
+ usage(reflog_exists_usage); | ||
+ | ||
+ if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL)) | ||
+ die("invalid ref format: %s", argv[start]); | ||
+ return !reflog_exists(argv[start]); | ||
+} | ||
+ | ||
/* | ||
* main "reflog" | ||
*/ | ||
static const char reflog_usage[] = | ||
-"git reflog [ show | expire | delete ]"; | ||
+"git reflog [ show | expire | delete | exists ]"; | ||
int cmd_reflog(int argc, const char **argv, const char *prefix) | ||
{ | ||
@@ -724,5 +752,8 @@ int cmd_reflog(int argc, const char **argv, const char *prefix) | ||
if (!strcmp(argv[1], "delete")) | ||
return cmd_reflog_delete(argc - 1, argv + 1, prefix); | ||
+ if (!strcmp(argv[1], "exists")) | ||
+ return cmd_reflog_exists(argc - 1, argv + 1, prefix); | ||
+ | ||
return cmd_log_reflog(argc, argv, prefix); | ||
} |
View
40
builtin/remote.c
@@ -581,7 +581,6 @@ static int migrate_file(struct remote *remote) | ||
{ | ||
struct strbuf buf = STRBUF_INIT; | ||
int i; | ||
- const char *path = NULL; | ||
strbuf_addf(&buf, "remote.%s.url", remote->name); | ||
for (i = 0; i < remote->url_nr; i++) | ||
@@ -601,11 +600,9 @@ static int migrate_file(struct remote *remote) | ||
return error(_("Could not append '%s' to '%s'"), | ||
remote->fetch_refspec[i], buf.buf); | ||
if (remote->origin == REMOTE_REMOTES) | ||
- path = git_path("remotes/%s", remote->name); | ||
+ unlink_or_warn(git_path("remotes/%s", remote->name)); | ||
else if (remote->origin == REMOTE_BRANCHES) | ||
- path = git_path("branches/%s", remote->name); | ||
- if (path) | ||
- unlink_or_warn(path); | ||
+ unlink_or_warn(git_path("branches/%s", remote->name)); | ||
return 0; | ||
} | ||
@@ -746,26 +743,6 @@ static int mv(int argc, const char **argv) | ||
return 0; | ||
} | ||
-static int remove_branches(struct string_list *branches) | ||
-{ | ||
- struct strbuf err = STRBUF_INIT; | ||
- int i, result = 0; | ||
- | ||
- if (repack_without_refs(branches, &err)) | ||
- result |= error("%s", err.buf); | ||
- strbuf_release(&err); | ||
- | ||
- for (i = 0; i < branches->nr; i++) { | ||
- struct string_list_item *item = branches->items + i; | ||
- const char *refname = item->string; | ||
- | ||
- if (delete_ref(refname, NULL, 0)) | ||
- result |= error(_("Could not remove branch %s"), refname); | ||
- } | ||
- | ||
- return result; | ||
-} | ||
- | ||
static int rm(int argc, const char **argv) | ||
{ | ||
struct option options[] = { | ||
@@ -822,7 +799,7 @@ static int rm(int argc, const char **argv) | ||
strbuf_release(&buf); | ||
if (!result) | ||
- result = remove_branches(&branches); | ||
+ result = delete_refs(&branches); | ||
string_list_clear(&branches, 0); | ||
if (skipped.nr) { | ||
@@ -1334,19 +1311,12 @@ static int prune_remote(const char *remote, int dry_run) | ||
string_list_append(&refs_to_prune, item->util); | ||
string_list_sort(&refs_to_prune); | ||
- if (!dry_run) { | ||
- struct strbuf err = STRBUF_INIT; | ||
- if (repack_without_refs(&refs_to_prune, &err)) | ||
- result |= error("%s", err.buf); | ||
- strbuf_release(&err); | ||
- } | ||
+ if (!dry_run) | ||
+ result |= delete_refs(&refs_to_prune); | ||
for_each_string_list_item(item, &states.stale) { | ||
const char *refname = item->util; | ||
- if (!dry_run) | ||
- result |= delete_ref(refname, NULL, 0); | ||
- | ||
if (dry_run) | ||
printf_ln(_(" * [would prune] %s"), | ||
abbrev_ref(refname, "refs/remotes/")); | ||
View
24
builtin/repack.c
@@ -285,8 +285,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) | ||
failed = 0; | ||
for_each_string_list_item(item, &names) { | ||
for (ext = 0; ext < ARRAY_SIZE(exts); ext++) { | ||
- const char *fname_old; | ||
- char *fname; | ||
+ char *fname, *fname_old; | ||
fname = mkpathdup("%s/pack-%s%s", packdir, | ||
item->string, exts[ext].name); | ||
if (!file_exists(fname)) { | ||
@@ -294,7 +293,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) | ||
continue; | ||
} | ||
- fname_old = mkpath("%s/old-%s%s", packdir, | ||
+ fname_old = mkpathdup("%s/old-%s%s", packdir, | ||
item->string, exts[ext].name); | ||
if (file_exists(fname_old)) | ||
if (unlink(fname_old)) | ||
@@ -302,10 +301,12 @@ int cmd_repack(int argc, const char **argv, const char *prefix) | ||
if (!failed && rename(fname, fname_old)) { | ||
free(fname); | ||
+ free(fname_old); | ||
failed = 1; | ||
break; | ||
} else { | ||
string_list_append(&rollback, fname); | ||
+ free(fname_old); | ||
} | ||
} | ||
if (failed) | ||
@@ -314,13 +315,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix) | ||
if (failed) { | ||
struct string_list rollback_failure = STRING_LIST_INIT_DUP; | ||
for_each_string_list_item(item, &rollback) { | ||
- const char *fname_old; | ||
- char *fname; | ||
+ char *fname, *fname_old; | ||
fname = mkpathdup("%s/%s", packdir, item->string); | ||
- fname_old = mkpath("%s/old-%s", packdir, item->string); | ||
+ fname_old = mkpathdup("%s/old-%s", packdir, item->string); | ||
if (rename(fname_old, fname)) | ||
string_list_append(&rollback_failure, fname); | ||
free(fname); | ||
+ free(fname_old); | ||
} | ||
if (rollback_failure.nr) { | ||
@@ -368,13 +369,14 @@ int cmd_repack(int argc, const char **argv, const char *prefix) | ||
/* Remove the "old-" files */ | ||
for_each_string_list_item(item, &names) { | ||
for (ext = 0; ext < ARRAY_SIZE(exts); ext++) { | ||
- const char *fname; | ||
- fname = mkpath("%s/old-%s%s", | ||
- packdir, | ||
- item->string, | ||
- exts[ext].name); | ||
+ char *fname; | ||
+ fname = mkpathdup("%s/old-%s%s", | ||
+ packdir, | ||
+ item->string, | ||
+ exts[ext].name); | ||
if (remove_path(fname)) | ||
warning(_("removing '%s' failed"), fname); | ||
+ free(fname); | ||
} | ||
} | ||
View
6
builtin/replace.c
@@ -104,9 +104,9 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn) | ||
continue; | ||
} | ||
full_hex = sha1_to_hex(sha1); | ||
- snprintf(ref, sizeof(ref), "refs/replace/%s", full_hex); | ||
+ snprintf(ref, sizeof(ref), "%s%s", git_replace_ref_base, full_hex); | ||
/* read_ref() may reuse the buffer */ | ||
- full_hex = ref + strlen("refs/replace/"); | ||
+ full_hex = ref + strlen(git_replace_ref_base); | ||
if (read_ref(ref, sha1)) { | ||
error("replace ref '%s' not found.", full_hex); | ||
had_error = 1; | ||
@@ -134,7 +134,7 @@ static void check_ref_valid(unsigned char object[20], | ||
int force) | ||
{ | ||
if (snprintf(ref, ref_size, | ||
- "refs/replace/%s", | ||
+ "%s%s", git_replace_ref_base, | ||
sha1_to_hex(object)) > ref_size - 1) | ||
die("replace ref name too long: %.*s...", 50, ref); | ||
if (check_refname_format(ref, 0)) | ||
View
18
builtin/rerere.c
@@ -50,7 +50,7 @@ static int diff_two(const char *file1, const char *label1, | ||
int cmd_rerere(int argc, const char **argv, const char *prefix) | ||
{ | ||
struct string_list merge_rr = STRING_LIST_INIT_DUP; | ||
- int i, fd, autoupdate = -1, flags = 0; | ||
+ int i, autoupdate = -1, flags = 0; | ||
struct option options[] = { | ||
OPT_SET_INT(0, "rerere-autoupdate", &autoupdate, | ||
@@ -79,18 +79,16 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) | ||
return rerere_forget(&pathspec); | ||
} | ||
- fd = setup_rerere(&merge_rr, flags); | ||
- if (fd < 0) | ||
- return 0; | ||
- | ||
if (!strcmp(argv[0], "clear")) { | ||
rerere_clear(&merge_rr); | ||
} else if (!strcmp(argv[0], "gc")) | ||
rerere_gc(&merge_rr); | ||
- else if (!strcmp(argv[0], "status")) | ||
+ else if (!strcmp(argv[0], "status")) { | ||
+ if (setup_rerere(&merge_rr, flags | RERERE_READONLY) < 0) | ||
+ return 0; | ||
for (i = 0; i < merge_rr.nr; i++) | ||
printf("%s\n", merge_rr.items[i].string); | ||
- else if (!strcmp(argv[0], "remaining")) { | ||
+ } else if (!strcmp(argv[0], "remaining")) { | ||
rerere_remaining(&merge_rr); | ||
for (i = 0; i < merge_rr.nr; i++) { | ||
if (merge_rr.items[i].util != RERERE_RESOLVED) | ||
@@ -100,13 +98,15 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) | ||
* string_list_clear() */ | ||
merge_rr.items[i].util = NULL; | ||
} | ||
- } else if (!strcmp(argv[0], "diff")) | ||
+ } else if (!strcmp(argv[0], "diff")) { | ||
+ if (setup_rerere(&merge_rr, flags | RERERE_READONLY) < 0) | ||
+ return 0; | ||
for (i = 0; i < merge_rr.nr; i++) { | ||
const char *path = merge_rr.items[i].string; | ||
const char *name = (const char *)merge_rr.items[i].util; | ||
diff_two(rerere_path(name, "preimage"), path, path, path); | ||
} | ||
- else | ||
+ } else | ||
usage_with_options(rerere_usage, options); | ||
string_list_clear(&merge_rr, 1); | ||
View
2
builtin/reset.c
@@ -36,7 +36,7 @@ static const char *reset_type_names[] = { | ||
static inline int is_merge(void) | ||
{ | ||
- return !access(git_path("MERGE_HEAD"), F_OK); | ||
+ return !access(git_path_merge_head(), F_OK); | ||
} | ||
static int reset_index(const unsigned char *sha1, int reset_type, int quiet) | ||
View
3
builtin/rev-list.c
@@ -350,6 +350,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) | ||
revs.diff) | ||
usage(rev_list_usage); | ||
+ if (revs.show_notes) | ||
+ die(_("rev-list does not support display of notes")); | ||
+ | ||
save_commit_buffer = (revs.verbose_header || | ||
revs.grep_filter.pattern_list || | ||
revs.grep_filter.header_list); | ||
View
57
builtin/rev-parse.c
@@ -371,6 +371,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) | ||
N_("output in stuck long form")), | ||
OPT_END(), | ||
}; | ||
+ static const char * const flag_chars = "*=?!"; | ||
struct strbuf sb = STRBUF_INIT, parsed = STRBUF_INIT; | ||
const char **usage = NULL; | ||
@@ -400,7 +401,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) | ||
/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */ | ||
while (strbuf_getline(&sb, stdin, '\n') != EOF) { | ||
const char *s; | ||
- const char *end; | ||
+ const char *help; | ||
struct option *o; | ||
if (!sb.len) | ||
@@ -410,54 +411,56 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) | ||
memset(opts + onb, 0, sizeof(opts[onb])); | ||
o = &opts[onb++]; | ||
- s = strchr(sb.buf, ' '); | ||
- if (!s || *sb.buf == ' ') { | ||
+ help = strchr(sb.buf, ' '); | ||
+ if (!help || *sb.buf == ' ') { | ||
o->type = OPTION_GROUP; | ||
o->help = xstrdup(skipspaces(sb.buf)); | ||
continue; | ||
} | ||
o->type = OPTION_CALLBACK; | ||
- o->help = xstrdup(skipspaces(s)); | ||
+ o->help = xstrdup(skipspaces(help)); | ||
o->value = &parsed; | ||
o->flags = PARSE_OPT_NOARG; | ||
o->callback = &parseopt_dump; | ||
- /* Possible argument name hint */ | ||
- end = s; | ||
- while (s > sb.buf && strchr("*=?!", s[-1]) == NULL) | ||
- --s; | ||
- if (s != sb.buf && s != end) | ||
- o->argh = xmemdupz(s, end - s); | ||
- if (s == sb.buf) | ||
- s = end; | ||
- | ||
- while (s > sb.buf && strchr("*=?!", s[-1])) { | ||
- switch (*--s) { | ||
+ /* name(s) */ | ||
+ s = strpbrk(sb.buf, flag_chars); | ||
+ if (s == NULL) | ||
+ s = help; | ||
+ | ||
+ if (s - sb.buf == 1) /* short option only */ | ||
+ o->short_name = *sb.buf; | ||
+ else if (sb.buf[1] != ',') /* long option only */ | ||
+ o->long_name = xmemdupz(sb.buf, s - sb.buf); | ||
+ else { | ||
+ o->short_name = *sb.buf; | ||
+ o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2); | ||
+ } | ||
+ | ||
+ /* flags */ | ||
+ while (s < help) { | ||
+ switch (*s++) { | ||
case '=': | ||
o->flags &= ~PARSE_OPT_NOARG; | ||
- break; | ||
+ continue; | ||
case '?': | ||
o->flags &= ~PARSE_OPT_NOARG; | ||
o->flags |= PARSE_OPT_OPTARG; | ||
- break; | ||
+ continue; | ||
case '!': | ||
o->flags |= PARSE_OPT_NONEG; | ||
- break; | ||
+ continue; | ||
case '*': | ||
o->flags |= PARSE_OPT_HIDDEN; | ||
- break; | ||
+ continue; | ||
} | ||
+ s--; | ||
+ break; | ||
} | ||
- if (s - sb.buf == 1) /* short option only */ | ||
- o->short_name = *sb.buf; | ||
- else if (sb.buf[1] != ',') /* long option only */ | ||
- o->long_name = xmemdupz(sb.buf, s - sb.buf); | ||
- else { | ||
- o->short_name = *sb.buf; | ||
- o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2); | ||
- } | ||
+ if (s < help) | ||
+ o->argh = xmemdupz(s, help - s); | ||
} | ||
strbuf_release(&sb); | ||
View
191
builtin/send-pack.c
@@ -11,10 +11,16 @@ | ||
#include "transport.h" | ||
#include "version.h" | ||
#include "sha1-array.h" | ||
+#include "gpg-interface.h" | ||
+#include "gettext.h" | ||
-static const char send_pack_usage[] = | ||
-"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [--atomic] [<host>:]<directory> [<ref>...]\n" | ||
-" --all and explicit <ref> specification are mutually exclusive."; | ||
+static const char * const send_pack_usage[] = { | ||
+ N_("git send-pack [--all | --mirror] [--dry-run] [--force] " | ||
+ "[--receive-pack=<git-receive-pack>] [--verbose] [--thin] [--atomic] " | ||
+ "[<host>:]<directory> [<ref>...]\n" | ||
+ " --all and explicit <ref> specification are mutually exclusive."), | ||
+ NULL, | ||
+}; | ||
static struct send_pack_args args; | ||
@@ -91,6 +97,31 @@ static void print_helper_status(struct ref *ref) | ||
strbuf_release(&buf); | ||
} | ||
+static int send_pack_config(const char *k, const char *v, void *cb) | ||
+{ | ||
+ git_gpg_config(k, v, NULL); | ||
+ | ||
+ if (!strcmp(k, "push.gpgsign")) { | ||
+ const char *value; | ||
+ if (!git_config_get_value("push.gpgsign", &value)) { | ||
+ switch (git_config_maybe_bool("push.gpgsign", value)) { | ||
+ case 0: | ||
+ args.push_cert = SEND_PACK_PUSH_CERT_NEVER; | ||
+ break; | ||
+ case 1: | ||
+ args.push_cert = SEND_PACK_PUSH_CERT_ALWAYS; | ||
+ break; | ||
+ default: | ||
+ if (value && !strcasecmp(value, "if-asked")) | ||
+ args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED; | ||
+ else | ||
+ return error("Invalid value for '%s'", k); | ||
+ } | ||
+ } | ||
+ } | ||
+ return 0; | ||
+} | ||
+ | ||
int cmd_send_pack(int argc, const char **argv, const char *prefix) | ||
{ | ||
int i, nr_refspecs = 0; | ||
@@ -106,114 +137,68 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) | ||
int ret; | ||
int helper_status = 0; | ||
int send_all = 0; | ||
+ int verbose = 0; | ||
const char *receivepack = "git-receive-pack"; | ||
+ unsigned dry_run = 0; | ||
+ unsigned send_mirror = 0; | ||
+ unsigned force_update = 0; | ||
+ unsigned quiet = 0; | ||
+ int push_cert = 0; | ||
+ unsigned use_thin_pack = 0; | ||
+ unsigned atomic = 0; | ||
+ unsigned stateless_rpc = 0; | ||
int flags; | ||
unsigned int reject_reasons; | ||
int progress = -1; | ||
int from_stdin = 0; | ||
struct push_cas_option cas = {0}; | ||
- argv++; | ||
- for (i = 1; i < argc; i++, argv++) { | ||
- const char *arg = *argv; | ||
- | ||
- if (*arg == '-') { | ||
- if (starts_with(arg, "--receive-pack=")) { | ||
- receivepack = arg + 15; | ||
- continue; | ||
- } | ||
- if (starts_with(arg, "--exec=")) { | ||
- receivepack = arg + 7; | ||
- continue; | ||
- } | ||
- if (starts_with(arg, "--remote=")) { | ||
- remote_name = arg + 9; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--all")) { | ||
- send_all = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--dry-run")) { | ||
- args.dry_run = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--mirror")) { | ||
- args.send_mirror = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--force")) { | ||
- args.force_update = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--quiet")) { | ||
- args.quiet = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--verbose")) { | ||
- args.verbose = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--signed")) { | ||
- args.push_cert = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--progress")) { | ||
- progress = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--no-progress")) { | ||
- progress = 0; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--thin")) { | ||
- args.use_thin_pack = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--atomic")) { | ||
- args.atomic = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--stateless-rpc")) { | ||
- args.stateless_rpc = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--stdin")) { | ||
- from_stdin = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--helper-status")) { | ||
- helper_status = 1; | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--" CAS_OPT_NAME)) { | ||
- if (parse_push_cas_option(&cas, NULL, 0) < 0) | ||
- exit(1); | ||
- continue; | ||
- } | ||
- if (!strcmp(arg, "--no-" CAS_OPT_NAME)) { | ||
- if (parse_push_cas_option(&cas, NULL, 1) < 0) | ||
- exit(1); | ||
- continue; | ||
- } | ||
- if (starts_with(arg, "--" CAS_OPT_NAME "=")) { | ||
- if (parse_push_cas_option(&cas, | ||
- strchr(arg, '=') + 1, 0) < 0) | ||
- exit(1); | ||
- continue; | ||
- } | ||
- usage(send_pack_usage); | ||
- } | ||
- if (!dest) { | ||
- dest = arg; | ||
- continue; | ||
- } | ||
- refspecs = (const char **) argv; | ||
- nr_refspecs = argc - i; | ||
- break; | ||
+ struct option options[] = { | ||
+ OPT__VERBOSITY(&verbose), | ||
+ OPT_STRING(0, "receive-pack", &receivepack, "receive-pack", N_("receive pack program")), | ||
+ OPT_STRING(0, "exec", &receivepack, "receive-pack", N_("receive pack program")), | ||
+ OPT_STRING(0, "remote", &remote_name, "remote", N_("remote name")), | ||
+ OPT_BOOL(0, "all", &send_all, N_("push all refs")), | ||
+ OPT_BOOL('n' , "dry-run", &dry_run, N_("dry run")), | ||
+ OPT_BOOL(0, "mirror", &send_mirror, N_("mirror all refs")), | ||
+ OPT_BOOL('f', "force", &force_update, N_("force updates")), | ||
+ { OPTION_CALLBACK, | ||
+ 0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"), | ||
+ PARSE_OPT_OPTARG, option_parse_push_signed }, | ||
+ OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), | ||
+ OPT_BOOL(0, "thin", &use_thin_pack, N_("use thin pack")), | ||
+ OPT_BOOL(0, "atomic", &atomic, N_("request atomic transaction on remote side")), | ||
+ OPT_BOOL(0, "stateless-rpc", &stateless_rpc, N_("use stateless RPC protocol")), | ||
+ OPT_BOOL(0, "stdin", &from_stdin, N_("read refs from stdin")), | ||
+ OPT_BOOL(0, "helper-status", &helper_status, N_("print status from remote helper")), | ||
+ { OPTION_CALLBACK, | ||
+ 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"), | ||
+ N_("require old value of ref to be at this value"), | ||
+ PARSE_OPT_OPTARG, parseopt_push_cas_option }, | ||
+ OPT_END() | ||
+ }; | ||
+ | ||
+ git_config(send_pack_config, NULL); | ||
+ argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0); | ||
+ if (argc > 0) { | ||
+ dest = argv[0]; | ||
+ refspecs = (const char **)(argv + 1); | ||
+ nr_refspecs = argc - 1; | ||
} | ||
+ | ||
if (!dest) | ||
- usage(send_pack_usage); | ||
+ usage_with_options(send_pack_usage, options); | ||
+ | ||
+ args.verbose = verbose; | ||
+ args.dry_run = dry_run; | ||
+ args.send_mirror = send_mirror; | ||
+ args.force_update = force_update; | ||
+ args.quiet = quiet; | ||
+ args.push_cert = push_cert; | ||
+ args.progress = progress; | ||
+ args.use_thin_pack = use_thin_pack; | ||
+ args.atomic = atomic; | ||
+ args.stateless_rpc = stateless_rpc; | ||
if (from_stdin) { | ||
struct argv_array all_refspecs = ARGV_ARRAY_INIT; | ||
@@ -242,7 +227,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) | ||
*/ | ||
if ((refspecs && (send_all || args.send_mirror)) || | ||
(send_all && args.send_mirror)) | ||
- usage(send_pack_usage); | ||
+ usage_with_options(send_pack_usage, options); | ||
if (remote_name) { | ||
remote = remote_get(remote_name); | ||
View
2
builtin/shortlog.c
@@ -138,7 +138,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit) | ||
ctx.abbrev = log->abbrev; | ||
ctx.subject = ""; | ||
ctx.after_subject = ""; | ||
- ctx.date_mode = DATE_NORMAL; | ||
+ ctx.date_mode.type = DATE_NORMAL; | ||
ctx.output_encoding = get_log_output_encoding(); | ||
pretty_print_commit(&ctx, commit, &ufbuf); | ||
buffer = ufbuf.buf; | ||
View
9
builtin/show-branch.c
@@ -730,7 +730,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) | ||
if (reflog) { | ||
struct object_id oid; | ||
- char nth_desc[256]; | ||
char *ref; | ||
int base = 0; | ||
unsigned int flags = 0; | ||
@@ -769,6 +768,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) | ||
for (i = 0; i < reflog; i++) { | ||
char *logmsg; | ||
+ char *nth_desc; | ||
const char *msg; | ||
unsigned long timestamp; | ||
int tz; | ||
@@ -784,11 +784,14 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) | ||
else | ||
msg++; | ||
reflog_msg[i] = xstrfmt("(%s) %s", | ||
- show_date(timestamp, tz, 1), | ||
+ show_date(timestamp, tz, | ||
+ DATE_MODE(RELATIVE)), | ||
msg); | ||
free(logmsg); | ||
- sprintf(nth_desc, "%s@{%d}", *av, base+i); | ||
+ | ||
+ nth_desc = xstrfmt("%s@{%d}", *av, base+i); | ||
append_ref(nth_desc, &oid, 1); | ||
+ free(nth_desc); | ||
} | ||
free(ref); | ||
} | ||
View
2
builtin/show-ref.c
@@ -8,7 +8,7 @@ | ||
static const char * const show_ref_usage[] = { | ||
N_("git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<pattern>...]"), | ||
- N_("git show-ref --exclude-existing[=pattern] < ref-list"), | ||
+ N_("git show-ref --exclude-existing[=<pattern>] < <ref-list>"), | ||
NULL | ||
}; | ||
View
5
builtin/tag.c
@@ -579,6 +579,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) | ||
struct create_tag_options opt; | ||
char *cleanup_arg = NULL; | ||
int annotate = 0, force = 0, lines = -1; | ||
+ int create_reflog = 0; | ||
int cmdmode = 0; | ||
const char *msgfile = NULL, *keyid = NULL; | ||
struct msg_arg msg = { 0, STRBUF_INIT }; | ||
@@ -605,6 +606,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) | ||
OPT_STRING('u', "local-user", &keyid, N_("key-id"), | ||
N_("use another key to sign the tag")), | ||
OPT__FORCE(&force, N_("replace the tag if exists")), | ||
+ OPT_BOOL(0, "create-reflog", &create_reflog, N_("create a reflog")), | ||
OPT_GROUP(N_("Tag listing options")), | ||
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")), | ||
@@ -733,7 +735,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) | ||
transaction = ref_transaction_begin(&err); | ||
if (!transaction || | ||
ref_transaction_update(transaction, ref.buf, object, prev, | ||
- 0, NULL, &err) || | ||
+ create_reflog ? REF_FORCE_CREATE_REFLOG : 0, | ||
+ NULL, &err) || | ||
ref_transaction_commit(transaction, &err)) | ||
die("%s", err.buf); | ||
ref_transaction_free(transaction); | ||
View
16
builtin/unpack-objects.c
@@ -20,6 +20,7 @@ static unsigned char buffer[4096]; | ||
static unsigned int offset, len; | ||
static off_t consumed_bytes; | ||
static git_SHA_CTX ctx; | ||
+static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; | ||
/* | ||
* When running under --strict mode, objects whose reachability are | ||
@@ -178,7 +179,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf) | ||
* that have reachability requirements and calls this function. | ||
* Verify its reachability and validity recursively and write it out. | ||
*/ | ||
-static int check_object(struct object *obj, int type, void *data) | ||
+static int check_object(struct object *obj, int type, void *data, struct fsck_options *options) | ||
{ | ||
struct obj_buffer *obj_buf; | ||
@@ -203,10 +204,10 @@ static int check_object(struct object *obj, int type, void *data) | ||
obj_buf = lookup_object_buffer(obj); | ||
if (!obj_buf) | ||
die("Whoops! Cannot find object '%s'", sha1_to_hex(obj->sha1)); | ||
- if (fsck_object(obj, obj_buf->buffer, obj_buf->size, 1, | ||
- fsck_error_function)) | ||
+ if (fsck_object(obj, obj_buf->buffer, obj_buf->size, &fsck_options)) | ||
die("Error in object"); | ||
- if (fsck_walk(obj, check_object, NULL)) | ||
+ fsck_options.walk = check_object; | ||
+ if (fsck_walk(obj, NULL, &fsck_options)) | ||
die("Error on reachable objects of %s", sha1_to_hex(obj->sha1)); | ||
write_cached_object(obj, obj_buf); | ||
return 0; | ||
@@ -217,7 +218,7 @@ static void write_rest(void) | ||
unsigned i; | ||
for (i = 0; i < nr_objects; i++) { | ||
if (obj_list[i].obj) | ||
- check_object(obj_list[i].obj, OBJ_ANY, NULL); | ||
+ check_object(obj_list[i].obj, OBJ_ANY, NULL, NULL); | ||
} | ||
} | ||
@@ -529,6 +530,11 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) | ||
strict = 1; | ||
continue; | ||
} | ||
+ if (skip_prefix(arg, "--strict=", &arg)) { | ||
+ strict = 1; | ||
+ fsck_set_msg_types(&fsck_options, arg); | ||
+ continue; | ||
+ } | ||
if (starts_with(arg, "--pack_header=")) { | ||
struct pack_header *hdr; | ||
char *c; | ||
View
35
builtin/update-ref.c
@@ -14,6 +14,7 @@ static const char * const git_update_ref_usage[] = { | ||
static char line_termination = '\n'; | ||
static int update_flags; | ||
+static unsigned create_reflog_flag; | ||
static const char *msg; | ||
/* | ||
@@ -200,7 +201,8 @@ static const char *parse_cmd_update(struct ref_transaction *transaction, | ||
if (ref_transaction_update(transaction, refname, | ||
new_sha1, have_old ? old_sha1 : NULL, | ||
- update_flags, msg, &err)) | ||
+ update_flags | create_reflog_flag, | ||
+ msg, &err)) | ||
die("%s", err.buf); | ||
update_flags = 0; | ||
@@ -231,7 +233,8 @@ static const char *parse_cmd_create(struct ref_transaction *transaction, | ||
die("create %s: extra input: %s", refname, next); | ||
if (ref_transaction_create(transaction, refname, new_sha1, | ||
- update_flags, msg, &err)) | ||
+ update_flags | create_reflog_flag, | ||
+ msg, &err)) | ||
die("%s", err.buf); | ||
update_flags = 0; | ||
@@ -354,6 +357,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) | ||
unsigned char sha1[20], oldsha1[20]; | ||
int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0; | ||
unsigned int flags = 0; | ||
+ int create_reflog = 0; | ||
struct option options[] = { | ||
OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")), | ||
OPT_BOOL('d', NULL, &delete, N_("delete the reference")), | ||
@@ -361,6 +365,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) | ||
N_("update <refname> not the one it points to")), | ||
OPT_BOOL('z', NULL, &end_null, N_("stdin has NUL-terminated arguments")), | ||
OPT_BOOL( 0 , "stdin", &read_stdin, N_("read updates from stdin")), | ||
+ OPT_BOOL( 0 , "create-reflog", &create_reflog, N_("create a reflog")), | ||
OPT_END(), | ||
}; | ||
@@ -370,6 +375,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) | ||
if (msg && !*msg) | ||
die("Refusing to perform update with empty message."); | ||
+ create_reflog_flag = create_reflog ? REF_FORCE_CREATE_REFLOG : 0; | ||
+ | ||
if (read_stdin) { | ||
struct strbuf err = STRBUF_INIT; | ||
struct ref_transaction *transaction; | ||
@@ -408,15 +415,29 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) | ||
die("%s: not a valid SHA1", value); | ||
} | ||
- hashclr(oldsha1); /* all-zero hash in case oldval is the empty string */ | ||
- if (oldval && *oldval && get_sha1(oldval, oldsha1)) | ||
- die("%s: not a valid old SHA1", oldval); | ||
+ if (oldval) { | ||
+ if (!*oldval) | ||
+ /* | ||
+ * The empty string implies that the reference | ||
+ * must not already exist: | ||
+ */ | ||
+ hashclr(oldsha1); | ||
+ else if (get_sha1(oldval, oldsha1)) | ||
+ die("%s: not a valid old SHA1", oldval); | ||
+ } | ||
if (no_deref) | ||
flags = REF_NODEREF; | ||
if (delete) | ||
- return delete_ref(refname, oldval ? oldsha1 : NULL, flags); | ||
+ /* | ||
+ * For purposes of backwards compatibility, we treat | ||
+ * NULL_SHA1 as "don't care" here: | ||
+ */ | ||
+ return delete_ref(refname, | ||
+ (oldval && !is_null_sha1(oldsha1)) ? oldsha1 : NULL, | ||
+ flags); | ||
else | ||
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL, | ||
- flags, UPDATE_REFS_DIE_ON_ERR); | ||
+ flags | create_reflog_flag, | ||
+ UPDATE_REFS_DIE_ON_ERR); | ||
} |
View
25
builtin/verify-commit.c
@@ -18,25 +18,21 @@ static const char * const verify_commit_usage[] = { | ||
NULL | ||
}; | ||
-static int run_gpg_verify(const unsigned char *sha1, const char *buf, unsigned long size, int verbose) | ||
+static int run_gpg_verify(const unsigned char *sha1, const char *buf, unsigned long size, unsigned flags) | ||
{ | ||
struct signature_check signature_check; | ||
+ int ret; | ||
memset(&signature_check, 0, sizeof(signature_check)); | ||
- check_commit_signature(lookup_commit(sha1), &signature_check); | ||
- | ||
- if (verbose && signature_check.payload) | ||
- fputs(signature_check.payload, stdout); | ||
- | ||
- if (signature_check.gpg_output) | ||
- fputs(signature_check.gpg_output, stderr); | ||
+ ret = check_commit_signature(lookup_commit(sha1), &signature_check); | ||
+ print_signature_buffer(&signature_check, flags); | ||
signature_check_clear(&signature_check); | ||
- return signature_check.result != 'G'; | ||
+ return ret; | ||
} | ||
-static int verify_commit(const char *name, int verbose) | ||
+static int verify_commit(const char *name, unsigned flags) | ||
{ | ||
enum object_type type; | ||
unsigned char sha1[20]; | ||
@@ -54,7 +50,7 @@ static int verify_commit(const char *name, int verbose) | ||
return error("%s: cannot verify a non-commit object of type %s.", | ||
name, typename(type)); | ||
- ret = run_gpg_verify(sha1, buf, size, verbose); | ||
+ ret = run_gpg_verify(sha1, buf, size, flags); | ||
free(buf); | ||
return ret; | ||
@@ -71,8 +67,10 @@ static int git_verify_commit_config(const char *var, const char *value, void *cb | ||
int cmd_verify_commit(int argc, const char **argv, const char *prefix) | ||
{ | ||
int i = 1, verbose = 0, had_error = 0; | ||
+ unsigned flags = 0; | ||
const struct option verify_commit_options[] = { | ||
OPT__VERBOSE(&verbose, N_("print commit contents")), | ||
+ OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW), | ||
OPT_END() | ||
}; | ||
@@ -83,11 +81,14 @@ int cmd_verify_commit(int argc, const char **argv, const char *prefix) | ||
if (argc <= i) | ||
usage_with_options(verify_commit_usage, verify_commit_options); | ||
+ if (verbose) | ||
+ flags |= GPG_VERIFY_VERBOSE; | ||
+ | ||
/* sometimes the program was terminated because this signal | ||
* was received in the process of writing the gpg input: */ | ||
signal(SIGPIPE, SIG_IGN); | ||
while (i < argc) | ||
- if (verify_commit(argv[i++], verbose)) | ||
+ if (verify_commit(argv[i++], flags)) | ||
had_error = 1; | ||
return had_error; | ||
} |
View
30
builtin/verify-tag.c
@@ -18,21 +18,30 @@ static const char * const verify_tag_usage[] = { | ||
NULL | ||
}; | ||
-static int run_gpg_verify(const char *buf, unsigned long size, int verbose) | ||
+static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags) | ||
{ | ||
+ struct signature_check sigc; | ||
int len; | ||
+ int ret; | ||
+ | ||
+ memset(&sigc, 0, sizeof(sigc)); | ||
len = parse_signature(buf, size); | ||
- if (verbose) | ||
- write_in_full(1, buf, len); | ||
- if (size == len) | ||
+ if (size == len) { | ||
+ if (flags & GPG_VERIFY_VERBOSE) | ||
+ write_in_full(1, buf, len); | ||
return error("no signature found"); | ||
+ } | ||
+ | ||
+ ret = check_signature(buf, len, buf + len, size - len, &sigc); | ||
+ print_signature_buffer(&sigc, flags); | ||
- return verify_signed_buffer(buf, len, buf + len, size - len, NULL, NULL); | ||
+ signature_check_clear(&sigc); | ||
+ return ret; | ||
} | ||
-static int verify_tag(const char *name, int verbose) | ||
+static int verify_tag(const char *name, unsigned flags) | ||
{ | ||
enum object_type type; | ||
unsigned char sha1[20]; | ||
@@ -52,7 +61,7 @@ static int verify_tag(const char *name, int verbose) | ||
if (!buf) | ||
return error("%s: unable to read file.", name); | ||
- ret = run_gpg_verify(buf, size, verbose); | ||
+ ret = run_gpg_verify(buf, size, flags); | ||
free(buf); | ||
return ret; | ||
@@ -69,8 +78,10 @@ static int git_verify_tag_config(const char *var, const char *value, void *cb) | ||
int cmd_verify_tag(int argc, const char **argv, const char *prefix) | ||
{ | ||
int i = 1, verbose = 0, had_error = 0; | ||
+ unsigned flags = 0; | ||
const struct option verify_tag_options[] = { | ||
OPT__VERBOSE(&verbose, N_("print tag contents")), | ||
+ OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW), | ||
OPT_END() | ||
}; | ||
@@ -81,11 +92,14 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) | ||
if (argc <= i) | ||
usage_with_options(verify_tag_usage, verify_tag_options); | ||
+ if (verbose) | ||
+ flags |= GPG_VERIFY_VERBOSE; | ||
+ | ||
/* sometimes the program was terminated because this signal | ||
* was received in the process of writing the gpg input: */ | ||
signal(SIGPIPE, SIG_IGN); | ||
while (i < argc) | ||
- if (verify_tag(argv[i++], verbose)) | ||
+ if (verify_tag(argv[i++], flags)) | ||
had_error = 1; | ||
return had_error; | ||
} |
View
131
builtin/worktree.c
@@ -3,6 +3,8 @@ | ||
#include "dir.h" | ||
#include "parse-options.h" | ||
#include "argv-array.h" | ||
+#include "branch.h" | ||
+#include "refs.h" | ||
#include "run-command.h" | ||
#include "sigchain.h" | ||
#include "refs.h" | ||
@@ -13,6 +15,13 @@ static const char * const worktree_usage[] = { | ||
NULL | ||
}; | ||
+struct add_opts { | ||
+ int force; | ||
+ int detach; | ||
+ const char *new_branch; | ||
+ int force_new_branch; | ||
+}; | ||
+ | ||
static int show_only; | ||
static int verbose; | ||
static unsigned long expire; | ||
@@ -172,19 +181,35 @@ static const char *worktree_basename(const char *path, int *olen) | ||
return name; | ||
} | ||
-static int add_worktree(const char *path, const char **child_argv) | ||
+static int add_worktree(const char *path, const char *refname, | ||
+ const struct add_opts *opts) | ||
{ | ||
struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT; | ||
struct strbuf sb = STRBUF_INIT; | ||
const char *name; | ||
struct stat st; | ||
struct child_process cp; | ||
+ struct argv_array child_env = ARGV_ARRAY_INIT; | ||
int counter = 0, len, ret; | ||
- unsigned char rev[20]; | ||
+ struct strbuf symref = STRBUF_INIT; | ||
+ struct commit *commit = NULL; | ||
if (file_exists(path) && !is_empty_dir(path)) | ||
die(_("'%s' already exists"), path); | ||
+ /* is 'refname' a branch or commit? */ | ||
+ if (opts->force_new_branch) /* definitely a branch */ | ||
+ ; | ||
+ else if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) && | ||
+ ref_exists(symref.buf)) { /* it's a branch */ | ||
+ if (!opts->force) | ||
+ die_if_checked_out(symref.buf); | ||
+ } else { /* must be a commit */ | ||
+ commit = lookup_commit_reference_by_name(refname); | ||
+ if (!commit) | ||
+ die(_("invalid reference: %s"), refname); | ||
+ } | ||
+ | ||
name = worktree_basename(path, &len); | ||
strbuf_addstr(&sb_repo, | ||
git_path("worktrees/%.*s", (int)(path + len - name), name)); | ||
@@ -213,7 +238,7 @@ static int add_worktree(const char *path, const char **child_argv) | ||
* after the preparation is over. | ||
*/ | ||
strbuf_addf(&sb, "%s/locked", sb_repo.buf); | ||
- write_file(sb.buf, 1, "initializing\n"); | ||
+ write_file(sb.buf, "initializing"); | ||
strbuf_addf(&sb_git, "%s/.git", path); | ||
if (safe_create_leading_directories_const(sb_git.buf)) | ||
@@ -223,37 +248,45 @@ static int add_worktree(const char *path, const char **child_argv) | ||
strbuf_reset(&sb); | ||
strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); | ||
- write_file(sb.buf, 1, "%s\n", real_path(sb_git.buf)); | ||
- write_file(sb_git.buf, 1, "gitdir: %s/worktrees/%s\n", | ||
+ write_file(sb.buf, "%s", real_path(sb_git.buf)); | ||
+ write_file(sb_git.buf, "gitdir: %s/worktrees/%s", | ||
real_path(get_git_common_dir()), name); | ||
/* | ||
* This is to keep resolve_ref() happy. We need a valid HEAD | ||
- * or is_git_directory() will reject the directory. Moreover, HEAD | ||
- * in the new worktree must resolve to the same value as HEAD in | ||
- * the current tree since the command invoked to populate the new | ||
- * worktree will be handed the branch/ref specified by the user. | ||
- * For instance, if the user asks for the new worktree to be based | ||
- * at HEAD~5, then the resolved HEAD~5 in the new worktree must | ||
- * match the resolved HEAD~5 in the current tree in order to match | ||
- * the user's expectation. | ||
+ * or is_git_directory() will reject the directory. Any value which | ||
+ * looks like an object ID will do since it will be immediately | ||
+ * replaced by the symbolic-ref or update-ref invocation in the new | ||
+ * worktree. | ||
*/ | ||
- if (!resolve_ref_unsafe("HEAD", 0, rev, NULL)) | ||
- die(_("unable to resolve HEAD")); | ||
strbuf_reset(&sb); | ||
strbuf_addf(&sb, "%s/HEAD", sb_repo.buf); | ||
- write_file(sb.buf, 1, "%s\n", sha1_to_hex(rev)); | ||
+ write_file(sb.buf, "0000000000000000000000000000000000000000"); | ||
strbuf_reset(&sb); | ||
strbuf_addf(&sb, "%s/commondir", sb_repo.buf); | ||
- write_file(sb.buf, 1, "../..\n"); | ||
+ write_file(sb.buf, "../.."); | ||
- fprintf_ln(stderr, _("Enter %s (identifier %s)"), path, name); | ||
+ fprintf_ln(stderr, _("Preparing %s (identifier %s)"), path, name); | ||
- setenv("GIT_CHECKOUT_NEW_WORKTREE", "1", 1); | ||
- setenv(GIT_DIR_ENVIRONMENT, sb_git.buf, 1); | ||
- setenv(GIT_WORK_TREE_ENVIRONMENT, path, 1); | ||
+ argv_array_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf); | ||
+ argv_array_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path); | ||
memset(&cp, 0, sizeof(cp)); | ||
cp.git_cmd = 1; | ||
- cp.argv = child_argv; | ||
+ | ||
+ if (commit) | ||
+ argv_array_pushl(&cp.args, "update-ref", "HEAD", | ||
+ sha1_to_hex(commit->object.sha1), NULL); | ||
+ else | ||
+ argv_array_pushl(&cp.args, "symbolic-ref", "HEAD", | ||
+ symref.buf, NULL); | ||
+ cp.env = child_env.argv; | ||
+ ret = run_command(&cp); | ||
+ if (ret) | ||
+ goto done; | ||
+ | ||
+ cp.argv = NULL; | ||
+ argv_array_clear(&cp.args); | ||
+ argv_array_pushl(&cp.args, "reset", "--hard", NULL); | ||
+ cp.env = child_env.argv; | ||
ret = run_command(&cp); | ||
if (!ret) { | ||
is_junk = 0; | ||
@@ -262,10 +295,13 @@ static int add_worktree(const char *path, const char **child_argv) | ||
junk_work_tree = NULL; | ||
junk_git_dir = NULL; | ||
} | ||
+done: | ||
strbuf_reset(&sb); | ||
strbuf_addf(&sb, "%s/locked", sb_repo.buf); | ||
unlink_or_warn(sb.buf); | ||
+ argv_array_clear(&child_env); | ||
strbuf_release(&sb); | ||
+ strbuf_release(&symref); | ||
strbuf_release(&sb_repo); | ||
strbuf_release(&sb_git); | ||
return ret; | ||
@@ -273,47 +309,54 @@ static int add_worktree(const char *path, const char **child_argv) | ||
static int add(int ac, const char **av, const char *prefix) | ||
{ | ||
- int force = 0, detach = 0; | ||
- const char *new_branch = NULL, *new_branch_force = NULL; | ||
+ struct add_opts opts; | ||
+ const char *new_branch_force = NULL; | ||
const char *path, *branch; | ||
- struct argv_array cmd = ARGV_ARRAY_INIT; | ||
struct option options[] = { | ||
- OPT__FORCE(&force, N_("checkout <branch> even if already checked out in other worktree")), | ||
- OPT_STRING('b', NULL, &new_branch, N_("branch"), | ||
+ OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")), | ||
+ OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), | ||
N_("create a new branch")), | ||
OPT_STRING('B', NULL, &new_branch_force, N_("branch"), | ||
N_("create or reset a branch")), | ||
- OPT_BOOL(0, "detach", &detach, N_("detach HEAD at named commit")), | ||
+ OPT_BOOL(0, "detach", &opts.detach, N_("detach HEAD at named commit")), | ||
OPT_END() | ||
}; | ||
+ memset(&opts, 0, sizeof(opts)); | ||
ac = parse_options(ac, av, prefix, options, worktree_usage, 0); | ||
- if (new_branch && new_branch_force) | ||
- die(_("-b and -B are mutually exclusive")); | ||
+ if (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1) | ||
+ die(_("-b, -B, and --detach are mutually exclusive")); | ||
if (ac < 1 || ac > 2) | ||
usage_with_options(worktree_usage, options); | ||
path = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0]; | ||
branch = ac < 2 ? "HEAD" : av[1]; | ||
- if (ac < 2 && !new_branch && !new_branch_force) { | ||
+ opts.force_new_branch = !!new_branch_force; | ||
+ if (opts.force_new_branch) | ||
+ opts.new_branch = new_branch_force; | ||
+ | ||
+ if (ac < 2 && !opts.new_branch && !opts.detach) { | ||
int n; | ||
const char *s = worktree_basename(path, &n); | ||
- new_branch = xstrndup(s, n); | ||
+ opts.new_branch = xstrndup(s, n); | ||
+ } | ||
+ | ||
+ if (opts.new_branch) { | ||
+ struct child_process cp; | ||
+ memset(&cp, 0, sizeof(cp)); | ||
+ cp.git_cmd = 1; | ||
+ argv_array_push(&cp.args, "branch"); | ||
+ if (opts.force_new_branch) | ||
+ argv_array_push(&cp.args, "--force"); | ||
+ argv_array_push(&cp.args, opts.new_branch); | ||
+ argv_array_push(&cp.args, branch); | ||
+ if (run_command(&cp)) | ||
+ return -1; | ||
+ branch = opts.new_branch; | ||
} | ||
- argv_array_push(&cmd, "checkout"); | ||
- if (force) | ||
- argv_array_push(&cmd, "--ignore-other-worktrees"); | ||
- if (new_branch) | ||
- argv_array_pushl(&cmd, "-b", new_branch, NULL); | ||
- if (new_branch_force) | ||
- argv_array_pushl(&cmd, "-B", new_branch_force, NULL); | ||
- if (detach) | ||
- argv_array_push(&cmd, "--detach"); | ||
- argv_array_push(&cmd, branch); | ||
- | ||
- return add_worktree(path, cmd.argv); | ||
+ return add_worktree(path, branch, &opts); | ||
} | ||
int cmd_worktree(int ac, const char **av, const char *prefix) | ||
View
26
bundle.c
@@ -235,7 +235,9 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs) | ||
return result; | ||
} | ||
-static int write_pack_data(int bundle_fd, struct lock_file *lock, struct rev_info *revs) | ||
+ | ||
+/* Write the pack data to bundle_fd, then close it if it is > 1. */ | ||
+static int write_pack_data(int bundle_fd, struct rev_info *revs) | ||
{ | ||
struct child_process pack_objects = CHILD_PROCESS_INIT; | ||
int i; | ||
@@ -250,13 +252,6 @@ static int write_pack_data(int bundle_fd, struct lock_file *lock, struct rev_inf | ||
if (start_command(&pack_objects)) | ||
return error(_("Could not spawn pack-objects")); | ||
- /* | ||
- * start_command closed bundle_fd if it was > 1 | ||
- * so set the lock fd to -1 so commit_lock_file() | ||
- * won't fail trying to close it. | ||
- */ | ||
- lock->fd = -1; | ||
- | ||
for (i = 0; i < revs->pending.nr; i++) { | ||
struct object *object = revs->pending.objects[i].item; | ||
if (object->flags & UNINTERESTING) | ||
@@ -416,10 +411,21 @@ int create_bundle(struct bundle_header *header, const char *path, | ||
bundle_to_stdout = !strcmp(path, "-"); | ||
if (bundle_to_stdout) | ||
bundle_fd = 1; | ||
- else | ||
+ else { | ||
bundle_fd = hold_lock_file_for_update(&lock, path, | ||
LOCK_DIE_ON_ERROR); | ||
+ /* | ||
+ * write_pack_data() will close the fd passed to it, | ||
+ * but commit_lock_file() will also try to close the | ||
+ * lockfile's fd. So make a copy of the file | ||
+ * descriptor to avoid trying to close it twice. | ||
+ */ | ||
+ bundle_fd = dup(bundle_fd); | ||
+ if (bundle_fd < 0) | ||
+ die_errno("unable to dup file descriptor"); | ||
+ } | ||
+ | ||
/* write signature */ | ||
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature)); | ||
@@ -445,7 +451,7 @@ int create_bundle(struct bundle_header *header, const char *path, | ||
return -1; | ||
/* write pack */ | ||
- if (write_pack_data(bundle_fd, &lock, &revs)) | ||
+ if (write_pack_data(bundle_fd, &revs)) | ||
return -1; | ||
if (!bundle_to_stdout) { | ||
View
29
cache-tree.c
@@ -592,7 +592,7 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat | ||
return it; | ||
} | ||
-int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) | ||
+int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix) | ||
{ | ||
int entries, was_valid, newfd; | ||
struct lock_file *lock_file; | ||
@@ -603,23 +603,23 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) | ||
*/ | ||
lock_file = xcalloc(1, sizeof(struct lock_file)); | ||
- newfd = hold_locked_index(lock_file, 1); | ||
+ newfd = hold_lock_file_for_update(lock_file, index_path, LOCK_DIE_ON_ERROR); | ||
- entries = read_cache(); | ||
+ entries = read_index_from(index_state, index_path); | ||
if (entries < 0) | ||
return WRITE_TREE_UNREADABLE_INDEX; | ||
if (flags & WRITE_TREE_IGNORE_CACHE_TREE) | ||
- cache_tree_free(&(active_cache_tree)); | ||
+ cache_tree_free(&index_state->cache_tree); | ||
- if (!active_cache_tree) | ||
- active_cache_tree = cache_tree(); | ||
+ if (!index_state->cache_tree) | ||
+ index_state->cache_tree = cache_tree(); | ||
- was_valid = cache_tree_fully_valid(active_cache_tree); | ||
+ was_valid = cache_tree_fully_valid(index_state->cache_tree); | ||
if (!was_valid) { | ||
- if (cache_tree_update(&the_index, flags) < 0) | ||
+ if (cache_tree_update(index_state, flags) < 0) | ||
return WRITE_TREE_UNMERGED_INDEX; | ||
if (0 <= newfd) { | ||
- if (!write_locked_index(&the_index, lock_file, COMMIT_LOCK)) | ||
+ if (!write_locked_index(index_state, lock_file, COMMIT_LOCK)) | ||
newfd = -1; | ||
} | ||
/* Not being able to write is fine -- we are only interested | ||
@@ -631,14 +631,14 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) | ||
} | ||
if (prefix) { | ||
- struct cache_tree *subtree = | ||
- cache_tree_find(active_cache_tree, prefix); | ||
+ struct cache_tree *subtree; | ||
+ subtree = cache_tree_find(index_state->cache_tree, prefix); | ||
if (!subtree) | ||
return WRITE_TREE_PREFIX_ERROR; | ||
hashcpy(sha1, subtree->sha1); | ||
} | ||
else | ||
- hashcpy(sha1, active_cache_tree->sha1); | ||
+ hashcpy(sha1, index_state->cache_tree->sha1); | ||
if (0 <= newfd) | ||
rollback_lock_file(lock_file); | ||
@@ -646,6 +646,11 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) | ||
return 0; | ||
} | ||
+int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) | ||
+{ | ||
+ return write_index_as_tree(sha1, &the_index, get_index_file(), flags, prefix); | ||
+} | ||
+ | ||
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) | ||
{ | ||
struct tree_desc desc; | ||
View
1
cache-tree.h
@@ -46,6 +46,7 @@ int update_main_cache_tree(int); | ||
#define WRITE_TREE_UNMERGED_INDEX (-2) | ||
#define WRITE_TREE_PREFIX_ERROR (-3) | ||
+int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix); | ||
int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix); | ||
void prime_cache_tree(struct index_state *, struct tree *); | ||
View
175
cache.h
@@ -397,6 +397,7 @@ static inline enum object_type object_type(unsigned int mode) | ||
#define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH" | ||
#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" | ||
#define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS" | ||
+#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE" | ||
#define GITATTRIBUTES_FILE ".gitattributes" | ||
#define INFOATTRIBUTES_FILE "info/attributes" | ||
#define ATTRIBUTE_MACRO_PREFIX "[attr]" | ||
@@ -446,7 +447,17 @@ extern int get_common_dir(struct strbuf *sb, const char *gitdir); | ||
extern const char *get_git_namespace(void); | ||
extern const char *strip_namespace(const char *namespaced_ref); | ||
extern const char *get_git_work_tree(void); | ||
-extern const char *read_gitfile(const char *path); | ||
+ | ||
+#define READ_GITFILE_ERR_STAT_FAILED 1 | ||
+#define READ_GITFILE_ERR_NOT_A_FILE 2 | ||
+#define READ_GITFILE_ERR_OPEN_FAILED 3 | ||
+#define READ_GITFILE_ERR_READ_FAILED 4 | ||
+#define READ_GITFILE_ERR_INVALID_FORMAT 5 | ||
+#define READ_GITFILE_ERR_NO_PATH 6 | ||
+#define READ_GITFILE_ERR_NOT_A_REPO 7 | ||
+#define READ_GITFILE_ERR_TOO_LARGE 8 | ||
+extern const char *read_gitfile_gently(const char *path, int *return_error_code); | ||
+#define read_gitfile(path) read_gitfile_gently((path), NULL) | ||
extern const char *resolve_gitdir(const char *suspect); | ||
extern void set_git_work_tree(const char *tree); | ||
@@ -585,8 +596,6 @@ extern void update_index_if_able(struct index_state *, struct lock_file *); | ||
extern int hold_locked_index(struct lock_file *, int); | ||
extern void set_alternate_index_output(const char *); | ||
-extern int delete_ref(const char *, const unsigned char *sha1, unsigned int flags); | ||
- | ||
/* Environment bits from configuration mechanism */ | ||
extern int trust_executable_bit; | ||
extern int trust_ctime; | ||
@@ -622,6 +631,7 @@ extern unsigned long pack_size_limit_cfg; | ||
* been sought but there were none. | ||
*/ | ||
extern int check_replace_refs; | ||
+extern char *git_replace_ref_base; | ||
extern int fsync_object_files; | ||
extern int core_preload_index; | ||
@@ -698,23 +708,60 @@ extern int check_repository_format(void); | ||
#define DATA_CHANGED 0x0020 | ||
#define TYPE_CHANGED 0x0040 | ||
+/* | ||
+ * Return a statically allocated filename, either generically (mkpath), in | ||
+ * the repository directory (git_path), or in a submodule's repository | ||
+ * directory (git_path_submodule). In all cases, note that the result | ||
+ * may be overwritten by another call to _any_ of the functions. Consider | ||
+ * using the safer "dup" or "strbuf" formats below (in some cases, the | ||
+ * unsafe versions have already been removed). | ||
+ */ | ||
+extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | ||
+extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | ||
+ | ||
extern char *mksnpath(char *buf, size_t n, const char *fmt, ...) | ||
__attribute__((format (printf, 3, 4))); | ||
extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) | ||
__attribute__((format (printf, 2, 3))); | ||
+extern void strbuf_git_path_submodule(struct strbuf *sb, const char *path, | ||
+ const char *fmt, ...) | ||
+ __attribute__((format (printf, 3, 4))); | ||
extern char *git_pathdup(const char *fmt, ...) | ||
__attribute__((format (printf, 1, 2))); | ||
extern char *mkpathdup(const char *fmt, ...) | ||
__attribute__((format (printf, 1, 2))); | ||
- | ||
-/* Return a statically allocated filename matching the sha1 signature */ | ||
-extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | ||
-extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | ||
-extern const char *git_path_submodule(const char *path, const char *fmt, ...) | ||
+extern char *git_pathdup_submodule(const char *path, const char *fmt, ...) | ||
__attribute__((format (printf, 2, 3))); | ||
+ | ||
extern void report_linked_checkout_garbage(void); | ||
/* | ||
+ * You can define a static memoized git path like: | ||
+ * | ||
+ * static GIT_PATH_FUNC(git_path_foo, "FOO"); | ||
+ * | ||
+ * or use one of the global ones below. | ||
+ */ | ||
+#define GIT_PATH_FUNC(func, filename) \ | ||
+ const char *func(void) \ | ||
+ { \ | ||
+ static char *ret; \ | ||
+ if (!ret) \ | ||
+ ret = git_pathdup(filename); \ | ||
+ return ret; \ | ||
+ } | ||
+ | ||
+const char *git_path_cherry_pick_head(void); | ||
+const char *git_path_revert_head(void); | ||
+const char *git_path_squash_msg(void); | ||
+const char *git_path_merge_msg(void); | ||
+const char *git_path_merge_rr(void); | ||
+const char *git_path_merge_mode(void); | ||
+const char *git_path_merge_head(void); | ||
+const char *git_path_fetch_head(void); | ||
+const char *git_path_shallow(void); | ||
+ | ||
+/* | ||
* Return the name of the file in the local object database that would | ||
* be used to store a loose object with the specified sha1. The | ||
* return value is a pointer to a statically allocated buffer that is | ||
@@ -935,7 +982,7 @@ extern int do_check_packed_object_crc; | ||
extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type); | ||
-extern int move_temp_to_file(const char *tmpfile, const char *filename); | ||
+extern int finalize_object_file(const char *tmpfile, const char *filename); | ||
extern int has_sha1_pack(const unsigned char *sha1); | ||
@@ -1020,76 +1067,10 @@ extern int get_oid_hex(const char *hex, struct object_id *sha1); | ||
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ | ||
extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */ | ||
-extern int read_ref_full(const char *refname, int resolve_flags, | ||
- unsigned char *sha1, int *flags); | ||
-extern int read_ref(const char *refname, unsigned char *sha1); | ||
-/* | ||
- * Resolve a reference, recursively following symbolic refererences. | ||
- * | ||
- * Store the referred-to object's name in sha1 and return the name of | ||
- * the non-symbolic reference that ultimately pointed at it. The | ||
- * return value, if not NULL, is a pointer into either a static buffer | ||
- * or the input ref. | ||
- * | ||
- * If the reference cannot be resolved to an object, the behavior | ||
- * depends on the RESOLVE_REF_READING flag: | ||
- * | ||
- * - If RESOLVE_REF_READING is set, return NULL. | ||
- * | ||
- * - If RESOLVE_REF_READING is not set, clear sha1 and return the name of | ||
- * the last reference name in the chain, which will either be a non-symbolic | ||
- * reference or an undefined reference. If this is a prelude to | ||
- * "writing" to the ref, the return value is the name of the ref | ||
- * that will actually be created or changed. | ||
- * | ||
- * If the RESOLVE_REF_NO_RECURSE flag is passed, only resolves one | ||
- * level of symbolic reference. The value stored in sha1 for a symbolic | ||
- * reference will always be null_sha1 in this case, and the return | ||
- * value is the reference that the symref refers to directly. | ||
- * | ||
- * If flags is non-NULL, set the value that it points to the | ||
- * combination of REF_ISPACKED (if the reference was found among the | ||
- * packed references), REF_ISSYMREF (if the initial reference was a | ||
- * symbolic reference), REF_BAD_NAME (if the reference name is ill | ||
- * formed --- see RESOLVE_REF_ALLOW_BAD_NAME below), and REF_ISBROKEN | ||
- * (if the ref is malformed or has a bad name). See refs.h for more detail | ||
- * on each flag. | ||
- * | ||
- * If ref is not a properly-formatted, normalized reference, return | ||
- * NULL. If more than MAXDEPTH recursive symbolic lookups are needed, | ||
- * give up and return NULL. | ||
- * | ||
- * RESOLVE_REF_ALLOW_BAD_NAME allows resolving refs even when their | ||
- * name is invalid according to git-check-ref-format(1). If the name | ||
- * is bad then the value stored in sha1 will be null_sha1 and the two | ||
- * flags REF_ISBROKEN and REF_BAD_NAME will be set. | ||
- * | ||
- * Even with RESOLVE_REF_ALLOW_BAD_NAME, names that escape the refs/ | ||
- * directory and do not consist of all caps and underscores cannot be | ||
- * resolved. The function returns NULL for such ref names. | ||
- * Caps and underscores refers to the special refs, such as HEAD, | ||
- * FETCH_HEAD and friends, that all live outside of the refs/ directory. | ||
- */ | ||
-#define RESOLVE_REF_READING 0x01 | ||
-#define RESOLVE_REF_NO_RECURSE 0x02 | ||
-#define RESOLVE_REF_ALLOW_BAD_NAME 0x04 | ||
-extern const char *resolve_ref_unsafe(const char *ref, int resolve_flags, unsigned char *sha1, int *flags); | ||
-extern char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags); | ||
- | ||
-extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref); | ||
-extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref); | ||
extern int interpret_branch_name(const char *str, int len, struct strbuf *); | ||
extern int get_sha1_mb(const char *str, unsigned char *sha1); | ||
-/* | ||
- * Return true iff abbrev_name is a possible abbreviation for | ||
- * full_name according to the rules defined by ref_rev_parse_rules in | ||
- * refs.c. | ||
- */ | ||
-extern int refname_match(const char *abbrev_name, const char *full_name); | ||
- | ||
-extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg); | ||
extern int validate_headref(const char *ref); | ||
extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); | ||
@@ -1105,18 +1086,30 @@ extern void *read_object_with_reference(const unsigned char *sha1, | ||
extern struct object *peel_to_type(const char *name, int namelen, | ||
struct object *o, enum object_type); | ||
-enum date_mode { | ||
- DATE_NORMAL = 0, | ||
- DATE_RELATIVE, | ||
- DATE_SHORT, | ||
- DATE_LOCAL, | ||
- DATE_ISO8601, | ||
- DATE_ISO8601_STRICT, | ||
- DATE_RFC2822, | ||
- DATE_RAW | ||
+struct date_mode { | ||
+ enum date_mode_type { | ||
+ DATE_NORMAL = 0, | ||
+ DATE_RELATIVE, | ||
+ DATE_SHORT, | ||
+ DATE_LOCAL, | ||
+ DATE_ISO8601, | ||
+ DATE_ISO8601_STRICT, | ||
+ DATE_RFC2822, | ||
+ DATE_STRFTIME, | ||
+ DATE_RAW | ||
+ } type; | ||
+ const char *strftime_fmt; | ||
}; | ||
-const char *show_date(unsigned long time, int timezone, enum date_mode mode); | ||
+/* | ||
+ * Convenience helper for passing a constant type, like: | ||
+ * | ||
+ * show_date(t, tz, DATE_MODE(NORMAL)); | ||
+ */ | ||
+#define DATE_MODE(t) date_mode_from_type(DATE_##t) | ||
+struct date_mode *date_mode_from_type(enum date_mode_type type); | ||
+ | ||
+const char *show_date(unsigned long time, int timezone, const struct date_mode *mode); | ||
void show_date_relative(unsigned long time, int tz, const struct timeval *now, | ||
struct strbuf *timebuf); | ||
int parse_date(const char *date, struct strbuf *out); | ||
@@ -1126,7 +1119,7 @@ void datestamp(struct strbuf *out); | ||
#define approxidate(s) approxidate_careful((s), NULL) | ||
unsigned long approxidate_careful(const char *, int *); | ||
unsigned long approxidate_relative(const char *date, const struct timeval *now); | ||
-enum date_mode parse_date_format(const char *format); | ||
+void parse_date_format(const char *format, struct date_mode *mode); | ||
int date_overflows(unsigned long date); | ||
#define IDENT_STRICT 1 | ||
@@ -1163,7 +1156,8 @@ extern int split_ident_line(struct ident_split *, const char *, int); | ||
* the ident_split. It will also sanity-check the values and produce | ||
* a well-known sentinel date if they appear bogus. | ||
*/ | ||
-const char *show_ident_date(const struct ident_split *id, enum date_mode mode); | ||
+const char *show_ident_date(const struct ident_split *id, | ||
+ const struct date_mode *mode); | ||
/* | ||
* Compare split idents for equality or strict ordering. Note that we | ||
@@ -1435,6 +1429,7 @@ extern int git_config_with_options(config_fn_t fn, void *, | ||
int respect_includes); | ||
extern int git_config_early(config_fn_t fn, void *, const char *repo_config); | ||
extern int git_parse_ulong(const char *, unsigned long *); | ||
+extern int git_parse_maybe_bool(const char *); | ||
extern int git_config_int(const char *, const char *); | ||
extern int64_t git_config_int64(const char *, const char *); | ||
extern unsigned long git_config_ulong(const char *, const char *); | ||
@@ -1446,6 +1441,7 @@ extern int git_config_pathname(const char **, const char *, const char *); | ||
extern int git_config_set_in_file(const char *, const char *, const char *); | ||
extern int git_config_set(const char *, const char *); | ||
extern int git_config_parse_key(const char *, char **, int *); | ||
+extern int git_config_key_is_valid(const char *key); | ||
extern int git_config_set_multivar(const char *, const char *, const char *, int); | ||
extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int); | ||
extern int git_config_rename_section(const char *, const char *); | ||
@@ -1582,8 +1578,9 @@ static inline ssize_t write_str_in_full(int fd, const char *str) | ||
{ | ||
return write_in_full(fd, str, strlen(str)); | ||
} | ||
-__attribute__((format (printf, 3, 4))) | ||
-extern int write_file(const char *path, int fatal, const char *fmt, ...); | ||
+ | ||
+extern int write_file(const char *path, const char *fmt, ...); | ||
+extern int write_file_gently(const char *path, const char *fmt, ...); | ||
/* pager.c */ | ||
extern void setup_pager(void); | ||
View
34
commit-slab.h
@@ -15,7 +15,13 @@ | ||
* - int *indegree_at(struct indegree *, struct commit *); | ||
* | ||
* This function locates the data associated with the given commit in | ||
- * the indegree slab, and returns the pointer to it. | ||
+ * the indegree slab, and returns the pointer to it. The location to | ||
+ * store the data is allocated as necessary. | ||
+ * | ||
+ * - int *indegree_peek(struct indegree *, struct commit *); | ||
+ * | ||
+ * This function is similar to indegree_at(), but it will return NULL | ||
+ * until a call to indegree_at() was made for the commit. | ||
* | ||
* - void init_indegree(struct indegree *); | ||
* void init_indegree_with_stride(struct indegree *, int); | ||
@@ -80,8 +86,9 @@ static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \ | ||
s->slab = NULL; \ | ||
} \ | ||
\ | ||
-static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \ | ||
- const struct commit *c) \ | ||
+static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s, \ | ||
+ const struct commit *c, \ | ||
+ int add_if_missing) \ | ||
{ \ | ||
int nth_slab, nth_slot; \ | ||
\ | ||
@@ -90,16 +97,33 @@ static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \ | ||
\ | ||
if (s->slab_count <= nth_slab) { \ | ||
int i; \ | ||
+ if (!add_if_missing) \ | ||
+ return NULL; \ | ||
REALLOC_ARRAY(s->slab, nth_slab + 1); \ | ||
stat_ ##slabname## realloc++; \ | ||
for (i = s->slab_count; i <= nth_slab; i++) \ | ||
s->slab[i] = NULL; \ | ||
s->slab_count = nth_slab + 1; \ | ||
} \ | ||
- if (!s->slab[nth_slab]) \ | ||
+ if (!s->slab[nth_slab]) { \ | ||
+ if (!add_if_missing) \ | ||
+ return NULL; \ | ||
s->slab[nth_slab] = xcalloc(s->slab_size, \ | ||
sizeof(**s->slab) * s->stride); \ | ||
- return &s->slab[nth_slab][nth_slot * s->stride]; \ | ||
+ } \ | ||
+ return &s->slab[nth_slab][nth_slot * s->stride]; \ | ||
+} \ | ||
+ \ | ||
+static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \ | ||
+ const struct commit *c) \ | ||
+{ \ | ||
+ return slabname##_at_peek(s, c, 1); \ | ||
+} \ | ||
+ \ | ||
+static MAYBE_UNUSED elemtype *slabname## _peek(struct slabname *s, \ | ||
+ const struct commit *c) \ | ||
+{ \ | ||
+ return slabname##_at_peek(s, c, 0); \ | ||
} \ | ||
\ | ||
static int stat_ ##slabname## realloc | ||
View
49
commit.c
@@ -245,7 +245,12 @@ void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size) | ||
const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep) | ||
{ | ||
- struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit); | ||
+ struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit); | ||
+ if (!v) { | ||
+ if (sizep) | ||
+ *sizep = 0; | ||
+ return NULL; | ||
+ } | ||
if (sizep) | ||
*sizep = v->size; | ||
return v->buffer; | ||
@@ -272,24 +277,31 @@ const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep) | ||
void unuse_commit_buffer(const struct commit *commit, const void *buffer) | ||
{ | ||
- struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit); | ||
- if (v->buffer != buffer) | ||
+ struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit); | ||
+ if (!(v && v->buffer == buffer)) | ||
free((void *)buffer); | ||
} | ||
void free_commit_buffer(struct commit *commit) | ||
{ | ||
- struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit); | ||
- free(v->buffer); | ||
- v->buffer = NULL; | ||
- v->size = 0; | ||
+ struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit); | ||
+ if (v) { | ||
+ free(v->buffer); | ||
+ v->buffer = NULL; | ||
+ v->size = 0; | ||
+ } | ||
} | ||
const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep) | ||
{ | ||
- struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit); | ||
+ struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit); | ||
void *ret; | ||
+ if (!v) { | ||
+ if (sizep) | ||
+ *sizep = 0; | ||
+ return NULL; | ||
+ } | ||
ret = v->buffer; | ||
if (sizep) | ||
*sizep = v->size; | ||
@@ -1232,33 +1244,24 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header | ||
free(buf); | ||
} | ||
-void check_commit_signature(const struct commit *commit, struct signature_check *sigc) | ||
+int check_commit_signature(const struct commit *commit, struct signature_check *sigc) | ||
{ | ||
struct strbuf payload = STRBUF_INIT; | ||
struct strbuf signature = STRBUF_INIT; | ||
- struct strbuf gpg_output = STRBUF_INIT; | ||
- struct strbuf gpg_status = STRBUF_INIT; | ||
- int status; | ||
+ int ret = 1; | ||
sigc->result = 'N'; | ||
if (parse_signed_commit(commit, &payload, &signature) <= 0) | ||
goto out; | ||
- status = verify_signed_buffer(payload.buf, payload.len, | ||
- signature.buf, signature.len, | ||
- &gpg_output, &gpg_status); | ||
- if (status && !gpg_output.len) | ||
- goto out; | ||
- sigc->payload = strbuf_detach(&payload, NULL); | ||
- sigc->gpg_output = strbuf_detach(&gpg_output, NULL); | ||
- sigc->gpg_status = strbuf_detach(&gpg_status, NULL); | ||
- parse_gpg_output(sigc); | ||
+ ret = check_signature(payload.buf, payload.len, signature.buf, | ||
+ signature.len, sigc); | ||
out: | ||
- strbuf_release(&gpg_status); | ||
- strbuf_release(&gpg_output); | ||
strbuf_release(&payload); | ||
strbuf_release(&signature); | ||
+ | ||
+ return ret; | ||
} | ||
View
4
commit.h
@@ -145,7 +145,7 @@ struct pretty_print_context { | ||
const char *subject; | ||
const char *after_subject; | ||
int preserve_subject; | ||
- enum date_mode date_mode; | ||
+ struct date_mode date_mode; | ||
unsigned date_mode_explicit:1; | ||
int need_8bit_cte; | ||
char *notes_message; | ||
@@ -379,7 +379,7 @@ extern void print_commit_list(struct commit_list *list, | ||
* at all. This may allocate memory for sig->gpg_output, sig->gpg_status, | ||
* sig->signer and sig->key. | ||
*/ | ||
-extern void check_commit_signature(const struct commit *commit, struct signature_check *sigc); | ||
+extern int check_commit_signature(const struct commit *commit, struct signature_check *sigc); | ||
int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused); | ||
View
2
compat/mingw.c
@@ -681,7 +681,7 @@ int pipe(int filedes[2]) | ||
return -1; | ||
} | ||
filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT); | ||
- if (filedes[0] < 0) { | ||
+ if (filedes[1] < 0) { | ||
close(filedes[0]); | ||
CloseHandle(h[1]); | ||
return -1; | ||
View
16
compat/poll/poll.c
@@ -446,7 +446,7 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) | ||
static HANDLE hEvent; | ||
WSANETWORKEVENTS ev; | ||
HANDLE h, handle_array[FD_SETSIZE + 2]; | ||
- DWORD ret, wait_timeout, nhandles; | ||
+ DWORD ret, wait_timeout, nhandles, start = 0, elapsed, orig_timeout = 0; | ||
fd_set rfds, wfds, xfds; | ||
BOOL poll_again; | ||
MSG msg; | ||
@@ -459,6 +459,12 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) | ||
return -1; | ||
} | ||
+ if (timeout != INFTIM) | ||
+ { | ||
+ orig_timeout = timeout; | ||
+ start = GetTickCount(); | ||
+ } | ||
+ | ||
if (!hEvent) | ||
hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
@@ -603,7 +609,13 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) | ||
rc++; | ||
} | ||
- if (!rc && timeout == INFTIM) | ||
+ if (!rc && orig_timeout && timeout != INFTIM) | ||
+ { | ||
+ elapsed = GetTickCount() - start; | ||
+ timeout = elapsed >= orig_timeout ? 0 : orig_timeout - elapsed; | ||
+ } | ||
+ | ||
+ if (!rc && timeout) | ||
{ | ||
SleepEx (1, TRUE); | ||
goto restart; | ||
View
64
config.c
@@ -618,7 +618,7 @@ unsigned long git_config_ulong(const char *name, const char *value) | ||
return ret; | ||
} | ||
-static int git_config_maybe_bool_text(const char *name, const char *value) | ||
+int git_parse_maybe_bool(const char *value) | ||
{ | ||
if (!value) | ||
return 1; | ||
@@ -637,7 +637,7 @@ static int git_config_maybe_bool_text(const char *name, const char *value) | ||
int git_config_maybe_bool(const char *name, const char *value) | ||
{ | ||
- int v = git_config_maybe_bool_text(name, value); | ||
+ int v = git_parse_maybe_bool(value); | ||
if (0 <= v) | ||
return v; | ||
if (git_parse_int(value, &v)) | ||
@@ -647,7 +647,7 @@ int git_config_maybe_bool(const char *name, const char *value) | ||
int git_config_bool_or_int(const char *name, const char *value, int *is_bool) | ||
{ | ||
- int v = git_config_maybe_bool_text(name, value); | ||
+ int v = git_parse_maybe_bool(value); | ||
if (0 <= v) { | ||
*is_bool = 1; | ||
return v; | ||
@@ -1848,7 +1848,7 @@ int git_config_set(const char *key, const char *value) | ||
* baselen - pointer to int which will hold the length of the | ||
* section + subsection part, can be NULL | ||
*/ | ||
-int git_config_parse_key(const char *key, char **store_key, int *baselen_) | ||
+static int git_config_parse_key_1(const char *key, char **store_key, int *baselen_, int quiet) | ||
{ | ||
int i, dot, baselen; | ||
const char *last_dot = strrchr(key, '.'); | ||
@@ -1859,12 +1859,14 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_) | ||
*/ | ||
if (last_dot == NULL || last_dot == key) { | ||
- error("key does not contain a section: %s", key); | ||
+ if (!quiet) | ||
+ error("key does not contain a section: %s", key); | ||
return -CONFIG_NO_SECTION_OR_NAME; | ||
} | ||
if (!last_dot[1]) { | ||
- error("key does not contain variable name: %s", key); | ||
+ if (!quiet) | ||
+ error("key does not contain variable name: %s", key); | ||
return -CONFIG_NO_SECTION_OR_NAME; | ||
} | ||
@@ -1875,7 +1877,8 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_) | ||
/* | ||
* Validate the key and while at it, lower case it for matching. | ||
*/ | ||
- *store_key = xmalloc(strlen(key) + 1); | ||
+ if (store_key) | ||
+ *store_key = xmalloc(strlen(key) + 1); | ||
dot = 0; | ||
for (i = 0; key[i]; i++) { | ||
@@ -1886,26 +1889,42 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_) | ||
if (!dot || i > baselen) { | ||
if (!iskeychar(c) || | ||
(i == baselen + 1 && !isalpha(c))) { | ||
- error("invalid key: %s", key); | ||
+ if (!quiet) | ||
+ error("invalid key: %s", key); | ||
goto out_free_ret_1; | ||
} | ||
c = tolower(c); | ||
} else if (c == '\n') { | ||
- error("invalid key (newline): %s", key); | ||
+ if (!quiet) | ||
+ error("invalid key (newline): %s", key); | ||
goto out_free_ret_1; | ||
} | ||
- (*store_key)[i] = c; | ||
+ if (store_key) | ||
+ (*store_key)[i] = c; | ||
} | ||
- (*store_key)[i] = 0; | ||
+ if (store_key) | ||
+ (*store_key)[i] = 0; | ||
return 0; | ||
out_free_ret_1: | ||
- free(*store_key); | ||
- *store_key = NULL; | ||
+ if (store_key) { | ||
+ free(*store_key); | ||
+ *store_key = NULL; | ||
+ } | ||
return -CONFIG_INVALID_KEY; | ||
} | ||
+int git_config_parse_key(const char *key, char **store_key, int *baselen) | ||
+{ | ||
+ return git_config_parse_key_1(key, store_key, baselen, 0); | ||
+} | ||
+ | ||
+int git_config_key_is_valid(const char *key) | ||
+{ | ||
+ return !git_config_parse_key_1(key, NULL, NULL, 1); | ||
+} | ||
+ | ||
/* | ||
* If value==NULL, unset in (remove from) config, | ||
* if value_regex!=NULL, disregard key/value pairs where value does not match. | ||
@@ -1935,7 +1954,7 @@ int git_config_set_multivar_in_file(const char *config_filename, | ||
const char *key, const char *value, | ||
const char *value_regex, int multi_replace) | ||
{ | ||
- int fd = -1, in_fd; | ||
+ int fd = -1, in_fd = -1; | ||
int ret; | ||
struct lock_file *lock = NULL; | ||
char *filename_buf = NULL; | ||
@@ -2065,10 +2084,11 @@ int git_config_set_multivar_in_file(const char *config_filename, | ||
goto out_free; | ||
} | ||
close(in_fd); | ||
+ in_fd = -1; | ||
- if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) { | ||
+ if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) { | ||
error("chmod on %s failed: %s", | ||
- lock->filename.buf, strerror(errno)); | ||
+ get_lock_file_path(lock), strerror(errno)); | ||
ret = CONFIG_NO_WRITE; | ||
goto out_free; | ||
} | ||
@@ -2148,10 +2168,12 @@ int git_config_set_multivar_in_file(const char *config_filename, | ||
free(filename_buf); | ||
if (contents) | ||
munmap(contents, contents_sz); | ||
+ if (in_fd >= 0) | ||
+ close(in_fd); | ||
return ret; | ||
write_err_out: | ||
- ret = write_error(lock->filename.buf); | ||
+ ret = write_error(get_lock_file_path(lock)); | ||
goto out_free; | ||
} | ||
@@ -2252,9 +2274,9 @@ int git_config_rename_section_in_file(const char *config_filename, | ||
fstat(fileno(config_file), &st); | ||
- if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) { | ||
+ if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) { | ||
ret = error("chmod on %s failed: %s", | ||
- lock->filename.buf, strerror(errno)); | ||
+ get_lock_file_path(lock), strerror(errno)); | ||
goto out; | ||
} | ||
@@ -2275,7 +2297,7 @@ int git_config_rename_section_in_file(const char *config_filename, | ||
} | ||
store.baselen = strlen(new_name); | ||
if (!store_write_section(out_fd, new_name)) { | ||
- ret = write_error(lock->filename.buf); | ||
+ ret = write_error(get_lock_file_path(lock)); | ||
goto out; | ||
} | ||
/* | ||
@@ -2301,7 +2323,7 @@ int git_config_rename_section_in_file(const char *config_filename, | ||
continue; | ||
length = strlen(output); | ||
if (write_in_full(out_fd, output, length) != length) { | ||
- ret = write_error(lock->filename.buf); | ||
+ ret = write_error(get_lock_file_path(lock)); | ||
goto out; | ||
} | ||
} | ||
View
22
contrib/completion/git-completion.bash
@@ -744,9 +744,8 @@ __git_compute_porcelain_commands () | ||
__git_get_config_variables () | ||
{ | ||
local section="$1" i IFS=$'\n' | ||
- for i in $(git --git-dir="$(__gitdir)" config --get-regexp "^$section\..*" 2>/dev/null); do | ||
- i="${i#$section.}" | ||
- echo "${i/ */}" | ||
+ for i in $(git --git-dir="$(__gitdir)" config --name-only --get-regexp "^$section\..*" 2>/dev/null); do | ||
+ echo "${i#$section.}" | ||
done | ||
} | ||
@@ -1667,7 +1666,10 @@ _git_push () | ||
_git_rebase () | ||
{ | ||
local dir="$(__gitdir)" | ||
- if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then | ||
+ if [ -f "$dir"/rebase-merge/interactive ]; then | ||
+ __gitcomp "--continue --skip --abort --edit-todo" | ||
+ return | ||
+ elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then | ||
__gitcomp "--continue --skip --abort" | ||
return | ||
fi | ||
@@ -1774,15 +1776,7 @@ __git_config_get_set_variables () | ||
c=$((--c)) | ||
done | ||
- git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null | | ||
- while read -r line | ||
- do | ||
- case "$line" in | ||
- *.*=*) | ||
- echo "${line/=*/}" | ||
- ;; | ||
- esac | ||
- done | ||
+ git --git-dir="$(__gitdir)" config $config_file --name-only --list 2>/dev/null | ||
} | ||
_git_config () | ||
@@ -1887,6 +1881,7 @@ _git_config () | ||
--get --get-all --get-regexp | ||
--add --unset --unset-all | ||
--remove-section --rename-section | ||
+ --name-only | ||
" | ||
return | ||
;; | ||
@@ -2118,6 +2113,7 @@ _git_config () | ||
http.postBuffer | ||
http.proxy | ||
http.sslCipherList | ||
+ http.sslVersion | ||
http.sslCAInfo | ||
http.sslCAPath | ||
http.sslCert | ||
View
2
contrib/completion/git-prompt.sh
@@ -491,7 +491,7 @@ __git_ps1 () | ||
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] && | ||
[ "$(git config --bool bash.showUntrackedFiles)" != "false" ] && | ||
- git ls-files --others --exclude-standard --error-unmatch -- ':/*' >/dev/null 2>/dev/null | ||
+ git ls-files --others --exclude-standard --directory --no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null | ||
then | ||
u="%${ZSH_VERSION+%}" | ||
fi | ||
View
4
contrib/examples/builtin-fetch--tool.c
@@ -516,7 +516,7 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix) | ||
if (argc != 8) | ||
return error("append-fetch-head takes 6 args"); | ||
- filename = git_path("FETCH_HEAD"); | ||
+ filename = git_path_fetch_head(); | ||
fp = fopen(filename, "a"); | ||
if (!fp) | ||
return error("cannot open %s: %s", filename, strerror(errno)); | ||
@@ -534,7 +534,7 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix) | ||
if (argc != 5) | ||
return error("fetch-native-store takes 3 args"); | ||
- filename = git_path("FETCH_HEAD"); | ||
+ filename = git_path_fetch_head(); | ||
fp = fopen(filename, "a"); | ||
if (!fp) | ||
return error("cannot open %s: %s", filename, strerror(errno)); | ||
View
14
git-am.sh → contrib/examples/git-am.sh
@@ -300,6 +300,7 @@ split_patches () { | ||
;; | ||
stgit) | ||
this=0 | ||
+ test 0 -eq "$#" && set -- - | ||
for stgit in "$@" | ||
do | ||
this=$(expr "$this" + 1) | ||
@@ -321,7 +322,7 @@ split_patches () { | ||
print "Subject: ", $_ ; | ||
$subject = 1; | ||
} | ||
- ' < "$stgit" > "$dotest/$msgnum" || clean_abort | ||
+ ' -- "$stgit" >"$dotest/$msgnum" || clean_abort | ||
done | ||
echo "$this" > "$dotest/last" | ||
this= | ||
@@ -329,6 +330,7 @@ split_patches () { | ||
;; | ||
hg) | ||
this=0 | ||
+ test 0 -eq "$#" && set -- - | ||
for hg in "$@" | ||
do | ||
this=$(( $this + 1 )) | ||
@@ -345,17 +347,17 @@ split_patches () { | ||
elsif (/^\# User /) { s/\# User/From:/ ; print ; } | ||
elsif (/^\# Date /) { | ||
my ($hashsign, $str, $time, $tz) = split ; | ||
- $tz = sprintf "%+05d", (0-$tz)/36; | ||
+ $tz_str = sprintf "%+05d", (0-$tz)/36; | ||
print "Date: " . | ||
strftime("%a, %d %b %Y %H:%M:%S ", | ||
- localtime($time)) | ||
- . "$tz\n"; | ||
+ gmtime($time-$tz)) | ||
+ . "$tz_str\n"; | ||
} elsif (/^\# /) { next ; } | ||
else { | ||
print "\n", $_ ; | ||
$subject = 1; | ||
} | ||
- ' <"$hg" >"$dotest/$msgnum" || clean_abort | ||
+ ' -- "$hg" >"$dotest/$msgnum" || clean_abort | ||
done | ||
echo "$this" >"$dotest/last" | ||
this= | ||
@@ -510,7 +512,7 @@ then | ||
git read-tree --reset -u $head_tree $head_tree && | ||
index_tree=$(git write-tree) && | ||
git read-tree -m -u $index_tree $head_tree | ||
- git read-tree $head_tree | ||
+ git read-tree -m $head_tree | ||
;; | ||
,t) | ||
if test -f "$dotest/rebasing" | ||
View
2
git-pull.sh → contrib/examples/git-pull.sh
@@ -295,7 +295,7 @@ test true = "$rebase" && { | ||
} | ||
orig_head=$(git rev-parse -q --verify HEAD) | ||
git fetch $verbosity $progress $dry_run $recurse_submodules $all $append \ | ||
-$upload_pack $force $tags $prune $keep $depth $unshallow $update_shallow \ | ||
+${upload_pack:+"$upload_pack"} $force $tags $prune $keep $depth $unshallow $update_shallow \ | ||
$refmap --update-head-ok "$@" || exit 1 | ||
test -z "$dry_run" || exit 0 | ||
View
2
contrib/subtree/git-subtree.sh
@@ -305,7 +305,7 @@ copy_commit() | ||
# We're going to set some environment vars here, so | ||
# do it in a subshell to get rid of them safely later | ||
debug copy_commit "{$1}" "{$2}" "{$3}" | ||
- git log -1 --pretty=format:'%an%n%ae%n%ad%n%cn%n%ce%n%cd%n%B' "$1" | | ||
+ git log -1 --pretty=format:'%an%n%ae%n%aD%n%cn%n%ce%n%cD%n%B' "$1" | | ||
( | ||
read GIT_AUTHOR_NAME | ||
read GIT_AUTHOR_EMAIL | ||
View
4
contrib/subtree/t/t7900-subtree.sh
@@ -94,6 +94,10 @@ test_expect_success 'add sub3' ' | ||
# Back to mainline | ||
cd .. | ||
+test_expect_success 'enable log.date=relative to catch errors' ' | ||
+ git config log.date relative | ||
+' | ||
+ | ||
test_expect_success 'add main4' ' | ||
create main4 && | ||
git commit -m "main4" && | ||
View
25
credential-cache--daemon.c
@@ -1,23 +1,11 @@ | ||
#include "cache.h" | ||
+#include "tempfile.h" | ||
#include "credential.h" | ||
#include "unix-socket.h" | ||
#include "sigchain.h" | ||
#include "parse-options.h" | ||
-static const char *socket_path; | ||
- | ||
-static void cleanup_socket(void) | ||
-{ | ||
- if (socket_path) | ||
- unlink(socket_path); | ||
-} | ||
- | ||
-static void cleanup_socket_on_signal(int sig) | ||
-{ | ||
- cleanup_socket(); | ||
- sigchain_pop(sig); | ||
- raise(sig); | ||
-} | ||
+static struct tempfile socket_file; | ||
struct credential_cache_entry { | ||
struct credential item; | ||
@@ -221,7 +209,6 @@ static void serve_cache(const char *socket_path, int debug) | ||
; /* nothing */ | ||
close(fd); | ||
- unlink(socket_path); | ||
} | ||
static const char permissions_advice[] = | ||
@@ -257,6 +244,7 @@ static void check_socket_directory(const char *path) | ||
int main(int argc, const char **argv) | ||
{ | ||
+ const char *socket_path; | ||
static const char *usage[] = { | ||
"git-credential-cache--daemon [opts] <socket_path>", | ||
NULL | ||
@@ -273,12 +261,11 @@ int main(int argc, const char **argv) | ||
if (!socket_path) | ||
usage_with_options(usage, options); | ||
- check_socket_directory(socket_path); | ||
- | ||
- atexit(cleanup_socket); | ||
- sigchain_push_common(cleanup_socket_on_signal); | ||
+ check_socket_directory(socket_path); | ||
+ register_tempfile(&socket_file, socket_path); | ||
serve_cache(socket_path, debug); | ||
+ delete_tempfile(&socket_file); | ||
return 0; | ||
} |
View
2
credential-store.c
@@ -52,7 +52,7 @@ static void print_entry(struct credential *c) | ||
static void print_line(struct strbuf *buf) | ||
{ | ||
strbuf_addch(buf, '\n'); | ||
- write_or_die(credential_lock.fd, buf->buf, buf->len); | ||
+ write_or_die(get_lock_file_fd(&credential_lock), buf->buf, buf->len); | ||
} | ||
static void rewrite_credential_file(const char *fn, struct credential *c, | ||
View
2
daemon.c
@@ -1376,7 +1376,7 @@ int main(int argc, char **argv) | ||
sanitize_stdfds(); | ||
if (pid_file) | ||
- write_file(pid_file, 1, "%"PRIuMAX"\n", (uintmax_t) getpid()); | ||
+ write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid()); | ||
/* prepare argv for serving-processes */ | ||
cld_argv = xmalloc(sizeof (char *) * (argc + 2)); | ||
View
0
date.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
diff.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
diff.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
dir.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
environment.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
fast-import.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
fetch-pack.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
fsck.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
fsck.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
generate-cmdlist.perl
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
generate-cmdlist.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gettext.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-bisect.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-compat-util.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-p4.py
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-rebase--interactive.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-send-email.perl
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-stash.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-submodule.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git-svn.perl
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
git.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/gitk
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/bg.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/ca.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/de.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/es.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/fr.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/hu.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/it.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/ja.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/pt_br.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/ru.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/sv.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gitk-git/po/vi.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gpg-interface.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
gpg-interface.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
http-backend.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
http.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
lockfile.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
lockfile.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
log-tree.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
notes-merge.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
notes-merge.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
notes-utils.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
notes-utils.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
notes.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
pager.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
parse-options-cb.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
parse-options.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
parse-options.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
path.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
perl/Git.pm
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
pkt-line.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/README
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/TEAMS
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/ca.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/de.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/fr.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/git.pot
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/sv.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/vi.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
po/zh_CN.po
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
pretty.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
read-cache.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
ref-filter.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
ref-filter.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
reflog-walk.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
reflog-walk.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
refs.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
refs.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
remote-curl.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
remote-testsvn.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
rerere.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
rerere.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
revision.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
revision.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
run-command.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
run-command.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
send-pack.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
send-pack.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
sequencer.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
setup.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
sha1_file.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
sha1_name.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
shallow.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
strbuf.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
strbuf.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
submodule-config.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
submodule-config.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
submodule.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
submodule.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/lib-rebase.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/perf/p7300-clean.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t0002-gitfile.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t0040-parse-options.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t0090-cache-tree.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1006-cat-file.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1090-sparse-checkout-scope.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1300-repo-config.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1400-update-ref.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1402-check-ref-format.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1410-reflog.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1411-reflog-show.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1450-fsck.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1502-rev-parse-parseopt.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1503-rev-parse-verify.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t1509-root-worktree.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t2019-checkout-ambiguous-ref.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t2025-worktree-add.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3020-ls-files-error-unmatch.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3200-branch.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3210-pack-refs.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3309-notes-merge-auto-resolve.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3310-notes-merge-manual-resolve.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3320-notes-merge-worktrees.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3404-rebase-interactive.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3415-rebase-autosquash.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3418-rebase-continue.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3901-i18n-patch.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t3903-stash.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t4018-diff-funcname.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t4018/fountain-scene
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t4150-am.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t4151-am-abort.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t4153-am-resume-override-opts.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t4202-log.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5004-archive-corner-cases.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5302-pack-index.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5312-prune-corruption.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5504-fetch-receive-strict.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5511-refspec.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5512-ls-remote.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5520-pull.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5601-clone.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5603-clone-dirname.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t5700-clone-reference.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t6030-bisect-porcelain.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t6120-describe.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t6300-for-each-ref.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t6501-freshen-objects.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7004-tag.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7006-pager.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7030-verify-tag.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7060-wtstatus.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7063-status-untracked-cache.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7300-clean.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7411-submodule-config.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7509-commit.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7510-signed-commit.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7512-status-help.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t7513-interpret-trailers.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t9000-addresses.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t9000/test.pl
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t9001-send-email.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t9300-fast-import.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t9821-git-p4-path-variations.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/t9903-bash-prompt.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/test-lib.sh
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
t/test-terminal.perl
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
tempfile.c
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
tempfile.h
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
0
test-date.c
Sorry, we could not display the changes to this file because there were too many other changes to display.