Merge branch 'np/types' into jc/fetch

* np/types: (253 commits)
  get rid of lookup_object_type()
  convert object type handling from a string to a number
  formalize typename(), and add its reverse type_from_string()
  sha1_file.c: don't ignore an error condition in sha1_loose_object_info()
  sha1_file.c: cleanup "offset" usage
  sha1_file.c: cleanup hdr usage
  git-apply: do not fix whitespaces on context lines.
  diff --cc: integer overflow given a 2GB-or-larger file
  mailinfo: do not get confused with logical lines that are too long.
  Documentation: link in 1.5.0.2 material to the top documentation page.
  Documentation: document remote.<name>.tagopt
  GIT 1.5.0.2
  git-remote: support remotes with a dot in the name
  Documentation: describe "-f/-t/-m" options to "git-remote add"
  diff --cc: fix display of symlink conflicts during a merge.
  merge-recursive: fix longstanding bug in merging symlinks
  merge-index: fix longstanding bug in merging symlinks
  diff --cached: give more sensible error message when HEAD is yet to be created.
  Update tests to use test-chmtime
  Add test-chmtime: a utility to change mtime on files
  ...
This commit is contained in:
Junio C Hamano 2007-02-27 02:27:26 -08:00
Родитель fee7c2c71d 0ab179504a
Коммит 88459358cd
174 изменённых файлов: 7684 добавлений и 3725 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -33,7 +33,6 @@ git-daemon
git-diff git-diff
git-diff-files git-diff-files
git-diff-index git-diff-index
git-diff-stages
git-diff-tree git-diff-tree
git-describe git-describe
git-fast-import git-fast-import
@ -101,7 +100,6 @@ git-repo-config
git-request-pull git-request-pull
git-rerere git-rerere
git-reset git-reset
git-resolve
git-rev-list git-rev-list
git-rev-parse git-rev-parse
git-revert git-revert
@ -141,6 +139,7 @@ git-whatchanged
git-write-tree git-write-tree
git-core-*/?* git-core-*/?*
gitweb/gitweb.cgi gitweb/gitweb.cgi
test-chmtime
test-date test-date
test-delta test-delta
test-dump-cache-tree test-dump-cache-tree

Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,42 @@
GIT v1.5.0.1 Release Notes
==========================
Fixes since v1.5.0
------------------
* Documentation updates
- Clarifications and corrections to 1.5.0 release notes.
- The main documentation did not link to git-remote documentation.
- Clarified introductory text of git-rebase documentation.
- Converted remaining mentions of update-index on Porcelain
documents to git-add/git-rm.
- Some i18n.* configuration variables were incorrectly
described as core.*; fixed.
* Bugfixes
- git-add and git-update-index on a filesystem on which
executable bits are unreliable incorrectly reused st_mode
bits even when the path changed between symlink and regular
file.
- git-daemon marks the listening sockets with FD_CLOEXEC so
that it won't be leaked into the children.
- segfault from git-blame when the mandatory pathname
parameter was missing was fixed; usage() message is given
instead.
- git-rev-list did not read $GIT_DIR/config file, which means
that did not honor i18n.logoutputencoding correctly.
* Tweaks
- sliding mmap() inefficiently mmaped the same region of a
packfile with an access pattern that used objects in the
reverse order. This has been made more efficient.

Просмотреть файл

@ -0,0 +1,65 @@
GIT v1.5.0.2 Release Notes
==========================
Fixes since v1.5.0.1
--------------------
* Bugfixes
- Automated merge conflict handling when changes to symbolic
links conflicted were completely broken. The merge-resolve
strategy created a regular file with conflict markers in it
in place of the symbolic link. The default strategy,
merge-recursive was even more broken. It removed the path
that was pointed at by the symbolic link. Both of these
problems have been fixed.
- 'git diff maint master next' did not correctly give combined
diff across three trees.
- 'git fast-import' portability fix for Solaris.
- 'git show-ref --verify' without arguments did not error out
but segfaulted.
- 'git diff :tracked-file `pwd`/an-untracked-file' gave an extra
slashes after a/ and b/.
- 'git format-patch' produced too long filenames if the commit
message had too long line at the beginning.
- Running 'make all' and then without changing anything
running 'make install' still rebuilt some files. This
was inconvenient when building as yourself and then
installing as root (especially problematic when the source
directory is on NFS and root is mapped to nobody).
- 'git-rerere' failed to deal with two unconflicted paths that
sorted next to each other.
- 'git-rerere' attempted to open(2) a symlink and failed if
there was a conflict. Since a conflicting change to a
symlink would not benefit from rerere anyway, the command
now ignores conflicting changes to symlinks.
- 'git-repack' did not like to pass more than 64 arguments
internally to underlying 'rev-list' logic, which made it
impossible to repack after accumulating many (small) packs
in the repository.
- 'git-diff' to review the combined diff during a conflicted
merge were not reading the working tree version correctly
when changes to a symbolic link conflicted. It should have
read the data using readlink(2) but read from the regular
file the symbolic link pointed at.
- 'git-remote' did not like period in a remote's name.
* Documentation updates
- added and clarified core.bare, core.legacyheaders configurations.
- updated "git-clone --depth" documentation.
* Assorted git-gui fixes.

Просмотреть файл

@ -25,12 +25,18 @@ Specifically, the available options are:
older clients over dumb transports (e.g. http) using older older clients over dumb transports (e.g. http) using older
versions of git will also be affected. versions of git will also be affected.
To let git use the new loose object format, you have to
set core.legacyheaders to false.
- Since v1.4.3, configuration repack.usedeltabaseoffset allows - Since v1.4.3, configuration repack.usedeltabaseoffset allows
packfile to be created in more space efficient format, which packfile to be created in more space efficient format, which
cannot be read by git older than that version. cannot be read by git older than that version.
The above two are not enabled by default and you explicitly have To let git use the new format for packfiles, you have to
to ask for them, because these two features make repositories set repack.usedeltabaseoffset to true.
The above two new features are not enabled by default and you
have to explicitly ask for them, because they make repositories
unreadable by older versions of git, and in v1.5.0 we still do unreadable by older versions of git, and in v1.5.0 we still do
not enable them by default for the same reason. We will change not enable them by default for the same reason. We will change
this default probably 1 year after 1.4.2's release, when it is this default probably 1 year after 1.4.2's release, when it is
@ -94,8 +100,8 @@ Updates in v1.5.0 since v1.4.4 series
entries for selected paths. entries for selected paths.
- git-update-index is much less visible. Many suggestions to - git-update-index is much less visible. Many suggestions to
use the command in git output and documentation have now been use the command in git output and documentation have now been
replaced by simpler commands such as "git add" or "git rm". replaced by simpler commands such as "git add" or "git rm".
* Repository layout and objects transfer * Repository layout and objects transfer
@ -217,7 +223,7 @@ Updates in v1.5.0 since v1.4.4 series
"branch@{Nth}" notation. "branch@{Nth}" notation.
- "git show-branch" learned showing the reflog data with the - "git show-branch" learned showing the reflog data with the
new -g option. "git log" has -s option to view reflog new -g option. "git log" has -g option to view reflog
entries in a more verbose manner. entries in a more verbose manner.
- git-branch knows how to rename branches and moves existing - git-branch knows how to rename branches and moves existing
@ -253,9 +259,6 @@ Updates in v1.5.0 since v1.4.4 series
above sentence, as git-prune does not remove things reachable above sentence, as git-prune does not remove things reachable
from reflog entries. from reflog entries.
- 'git-prune' by default does not remove _everything_
unreachable, as there is a one-day grace period built-in.
- There is a toplevel garbage collector script, 'git-gc', that - There is a toplevel garbage collector script, 'git-gc', that
runs periodic cleanup functions, including 'git-repack -a -d', runs periodic cleanup functions, including 'git-repack -a -d',
'git-reflog expire', 'git-pack-refs --prune', and 'git-rerere 'git-reflog expire', 'git-pack-refs --prune', and 'git-rerere
@ -291,12 +294,10 @@ Updates in v1.5.0 since v1.4.4 series
reset" to jump to arbitrary commit, while still keeping your reset" to jump to arbitrary commit, while still keeping your
HEAD detached. HEAD detached.
Going back to attached state (i.e. on a particular branch) by Remember that a detached state is volatile, i.e. it will be forgotten
"git checkout $branch" can lose the current stat you arrived as soon as you move away from it with the checkout or reset command,
in these ways, and "git checkout" refuses when the detached unless a branch is created from it as mentioned above. It is also
HEAD is not pointed by any existing ref (an existing branch, possible to rescue a lost detached state from the HEAD reflog.
a remote tracking branch or a tag). This safety can be
overridden with "git checkout -f $branch".
* Packed refs * Packed refs
@ -411,14 +412,14 @@ Updates in v1.5.0 since v1.4.4 series
* Foreign SCM interfaces * Foreign SCM interfaces
- git-svn now requires the Perl SVN:: libraries, the - git-svn now requires the Perl SVN:: libraries, the
command-line backend was too slow and limited. command-line backend was too slow and limited.
- the 'commit' subcommand of git-svn has been renamed to - the 'commit' subcommand of git-svn has been renamed to
'set-tree', and 'dcommit' is the recommended replacement for 'set-tree', and 'dcommit' is the recommended replacement for
day-to-day work. day-to-day work.
- git fast-import backend. - git fast-import backend.
* User support * User support
@ -447,7 +448,7 @@ Updates in v1.5.0 since v1.4.4 series
- There is a partial support for 'shallow' repositories that - There is a partial support for 'shallow' repositories that
keeps only recent history. A 'shallow clone' is created by keeps only recent history. A 'shallow clone' is created by
specifying how deep that truncated history should be specifying how deep that truncated history should be
(e.g. "git clone --depth=5 git://some.where/repo.git"). (e.g. "git clone --depth 5 git://some.where/repo.git").
Currently a shallow repository has number of limitations: Currently a shallow repository has number of limitations:

Просмотреть файл

@ -0,0 +1,44 @@
GIT v1.5.1 Release Notes
========================
Updates since v1.5.0
--------------------
* Deprecated commands and options.
- git-diff-stages and git-resolve have been removed.
* New commands and options.
- "git log" and friends take --reverse. This makes output
that typically goes reverse order in chronological order.
"git shortlog" usually lists commits in chronological order,
but with "--reverse", they are shown in reverse
chronological order.
- "git diff" learned --ignore-space-at-eol. This is a weaker
form of --ignore-space-change.
- "git name-rev" learned --refs=<pattern>, to limit the tags
used for naming the given revisions only to the ones
matching the given pattern.
* Updated behaviour of existing commands.
- "git diff" outputs a trailing HT when pathnames have embedded
SP on +++/--- header lines, in order to help "GNU patch" to
parse its output. "git apply" was already updated to accept
this modified output format since ce74618d (Sep 22, 2006).
* Hooks
- The sample update hook to show how to send out notification
e-mail was updated to show only new commits that appeared in
the repository. Earlier, it showed new commits that appeared
on the branch.
--
exec >/var/tmp/1
O=v1.5.0-49-g69bc0e2
echo O=`git describe master`
git shortlog --no-merges $O..master ^maint

Просмотреть файл

@ -90,7 +90,6 @@ git-describe mainporcelain
git-diff-files plumbinginterrogators git-diff-files plumbinginterrogators
git-diff-index plumbinginterrogators git-diff-index plumbinginterrogators
git-diff mainporcelain git-diff mainporcelain
git-diff-stages plumbinginterrogators
git-diff-tree plumbinginterrogators git-diff-tree plumbinginterrogators
git-fast-import ancillarymanipulators git-fast-import ancillarymanipulators
git-fetch mainporcelain git-fetch mainporcelain
@ -146,10 +145,10 @@ git-reflog ancillarymanipulators
git-relink ancillarymanipulators git-relink ancillarymanipulators
git-repack ancillarymanipulators git-repack ancillarymanipulators
git-config ancillarymanipulators git-config ancillarymanipulators
git-remote ancillarymanipulators
git-request-pull foreignscminterface git-request-pull foreignscminterface
git-rerere ancillaryinterrogators git-rerere ancillaryinterrogators
git-reset mainporcelain git-reset mainporcelain
git-resolve mainporcelain
git-revert mainporcelain git-revert mainporcelain
git-rev-list plumbinginterrogators git-rev-list plumbinginterrogators
git-rev-parse ancillaryinterrogators git-rev-parse ancillaryinterrogators

Просмотреть файл

@ -5,7 +5,8 @@ The git configuration file contains a number of variables that affect
the git command's behavior. `.git/config` file for each repository the git command's behavior. `.git/config` file for each repository
is used to store the information for that repository, and is used to store the information for that repository, and
`$HOME/.gitconfig` is used to store per user information to give `$HOME/.gitconfig` is used to store per user information to give
fallback values for `.git/config` file. fallback values for `.git/config` file. The file `/etc/gitconfig`
can be used to store system-wide defaults.
They can be used by both the git plumbing They can be used by both the git plumbing
and the porcelains. The variables are divided into sections, where and the porcelains. The variables are divided into sections, where
@ -142,6 +143,18 @@ core.preferSymlinkRefs::
This is sometimes needed to work with old scripts that This is sometimes needed to work with old scripts that
expect HEAD to be a symbolic link. expect HEAD to be a symbolic link.
core.bare::
If true this repository is assumed to be 'bare' and has no
working directory associated with it. If this is the case a
number of commands that require a working directory will be
disabled, such as gitlink:git-add[1] or gitlink:git-merge[1].
+
This setting is automatically guessed by gitlink:git-clone[1] or
gitlink:git-init[1] when the repository was created. By default a
repository that ends in "/.git" is assumed to be not bare (bare =
false), while all other repositories are assumed to be bare (bare
= true).
core.logAllRefUpdates:: core.logAllRefUpdates::
Updates to a ref <ref> is logged to the file Updates to a ref <ref> is logged to the file
"$GIT_DIR/logs/<ref>", by appending the new and old "$GIT_DIR/logs/<ref>", by appending the new and old
@ -180,10 +193,17 @@ core.compression::
slowest. slowest.
core.legacyheaders:: core.legacyheaders::
A boolean which enables the legacy object header format in case A boolean which
you want to interoperate with old clients accessing the object changes the format of loose objects so that they are more
database directly (where the "http://" and "rsync://" protocols efficient to pack and to send out of the repository over git
count as direct access). native protocol, since v1.4.2. However, loose objects
written in the new format cannot be read by git older than
that version; people fetching from your repository using
older versions of git over dumb transports (e.g. http)
will also be affected.
+
To let git use the new loose object format, you have to
set core.legacyheaders to false.
core.packedGitWindowSize:: core.packedGitWindowSize::
Number of bytes of a pack file to map into memory in a Number of bytes of a pack file to map into memory in a
@ -451,6 +471,10 @@ remote.<name>.push::
The default set of "refspec" for gitlink:git-push[1]. See The default set of "refspec" for gitlink:git-push[1]. See
gitlink:git-push[1]. gitlink:git-push[1].
remote.<name>.skipDefaultUpdate::
If true, this remote will be skipped by default when updating
using the remote subcommand of gitlink:git-remote[1].
remote.<name>.receivepack:: remote.<name>.receivepack::
The default program to execute on the remote side when pushing. See The default program to execute on the remote side when pushing. See
option \--exec of gitlink:git-push[1]. option \--exec of gitlink:git-push[1].
@ -459,6 +483,14 @@ remote.<name>.uploadpack::
The default program to execute on the remote side when fetching. See The default program to execute on the remote side when fetching. See
option \--exec of gitlink:git-fetch-pack[1]. option \--exec of gitlink:git-fetch-pack[1].
remote.<name>.tagopt::
Setting this value to --no-tags disables automatic tag following when fetching
from remote <name>
remotes.<group>::
The list of remotes which are fetched by "git remote update
<group>". See gitlink:git-remote[1].
repack.usedeltabaseoffset:: repack.usedeltabaseoffset::
Allow gitlink:git-repack[1] to create packs that uses Allow gitlink:git-repack[1] to create packs that uses
delta-base offset. Defaults to false. delta-base offset. Defaults to false.

Просмотреть файл

@ -106,7 +106,8 @@ directory tree, and renaming a file does not change the object that
file is associated with in any way. file is associated with in any way.
A blob is typically created when gitlink:git-update-index[1] A blob is typically created when gitlink:git-update-index[1]
is run, and its data can be accessed by gitlink:git-cat-file[1]. (or gitlink:git-add[1]) is run, and its data can be accessed by
gitlink:git-cat-file[1].
Tree Object Tree Object
~~~~~~~~~~~ ~~~~~~~~~~~
@ -587,4 +588,5 @@ stages to temporary files and calls a "merge" script on it:
git-merge-index git-merge-one-file hello.c git-merge-index git-merge-one-file hello.c
and that is what higher level `git resolve` is implemented with. and that is what higher level `git merge -s resolve` is implemented
with.

Просмотреть файл

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

Просмотреть файл

@ -140,6 +140,9 @@
-a:: -a::
Shorthand for "--text". Shorthand for "--text".
--ignore-space-at-eol::
Ignore changes in white spaces at EOL.
--ignore-space-change:: --ignore-space-change::
Ignore changes in amount of white space. This ignores white Ignore changes in amount of white space. This ignores white
space at line end, and consider all other sequences of one or space at line end, and consider all other sequences of one or

Просмотреть файл

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

Просмотреть файл

@ -61,7 +61,8 @@ OPTIONS
+ +
When a merge conflict happens, the index entries for conflicting When a merge conflict happens, the index entries for conflicting
paths are left unmerged, and you need to resolve the conflicts paths are left unmerged, and you need to resolve the conflicts
and mark the resolved paths with `git update-index`. and mark the resolved paths with `git add` (or `git rm` if the merge
should result in deletion of the path).
<new_branch>:: <new_branch>::
Name for the new branch. Name for the new branch.
@ -179,11 +180,11 @@ fatal: merge program failed
At this point, `git diff` shows the changes cleanly merged as in At this point, `git diff` shows the changes cleanly merged as in
the previous example, as well as the changes in the conflicted the previous example, as well as the changes in the conflicted
files. Edit and resolve the conflict and mark it resolved with files. Edit and resolve the conflict and mark it resolved with
`git update-index` as usual: `git add` as usual:
+ +
------------ ------------
$ edit frotz $ edit frotz
$ git update-index frotz $ git add frotz
------------ ------------

Просмотреть файл

@ -11,7 +11,7 @@ SYNOPSIS
[verse] [verse]
'git-clone' [--template=<template_directory>] [-l [-s]] [-q] [-n] [--bare] 'git-clone' [--template=<template_directory>] [-l [-s]] [-q] [-n] [--bare]
[-o <name>] [-u <upload-pack>] [--reference <repository>] [-o <name>] [-u <upload-pack>] [--reference <repository>]
[--depth=<depth>] <repository> [<directory>] [--depth <depth>] <repository> [<directory>]
DESCRIPTION DESCRIPTION
----------- -----------
@ -96,7 +96,7 @@ OPTIONS
if unset the templates are taken from the installation if unset the templates are taken from the installation
defined default, typically `/usr/share/git-core/templates`. defined default, typically `/usr/share/git-core/templates`.
--depth=<depth>:: --depth <depth>::
Create a 'shallow' clone with a history truncated to the Create a 'shallow' clone with a history truncated to the
specified number of revs. A shallow repository has specified number of revs. A shallow repository has
number of limitations (you cannot clone or fetch from number of limitations (you cannot clone or fetch from

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -3,7 +3,7 @@ git-fast-import(1)
NAME NAME
---- ----
git-fast-import - Backend for fast Git data importers. git-fast-import - Backend for fast Git data importers
SYNOPSIS SYNOPSIS

Просмотреть файл

@ -136,7 +136,7 @@ After seeing a conflict, you can do two things:
* Resolve the conflicts. `git-diff` would report only the * Resolve the conflicts. `git-diff` would report only the
conflicting paths because of the above 2. and 3.. Edit the conflicting paths because of the above 2. and 3.. Edit the
working tree files into a desirable shape, `git-update-index` working tree files into a desirable shape, `git-add` or `git-rm`
them, to make the index file contain what the merge result them, to make the index file contain what the merge result
should be, and run `git-commit` to commit the result. should be, and run `git-commit` to commit the result.

Просмотреть файл

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

Просмотреть файл

@ -13,11 +13,20 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
----------- -----------
git-rebase replaces <branch> with a new branch of the same name. When If <branch> is specified, git-rebase will perform an automatic
the --onto option is provided the new branch starts out with a HEAD equal `git checkout <branch>` before doing anything else. Otherwise
to <newbase>, otherwise it is equal to <upstream>. It then attempts to it remains on the current branch.
create a new commit for each commit from the original <branch> that does
not exist in the <upstream> branch. All changes made by commits in the current branch but that are not
in <upstream> are saved to a temporary area. This is the same set
of commits that would be shown by `git log <upstream>..HEAD`.
The current branch is reset to <upstream>, or <newbase> if the
--onto option was supplied. This has the exact same effect as
`git reset --hard <upstream>` (or <newbase>).
The commits that were previously saved into the temporary area are
then reapplied to the current branch, one by one, in order.
It is possible that a merge failure will prevent this process from being It is possible that a merge failure will prevent this process from being
completely automatic. You will have to resolve any such merge failure completely automatic. You will have to resolve any such merge failure
@ -26,9 +35,6 @@ that caused the merge failure with `git rebase --skip`. To restore the
original <branch> and remove the .dotest working files, use the command original <branch> and remove the .dotest working files, use the command
`git rebase --abort` instead. `git rebase --abort` instead.
Note that if <branch> is not specified on the command line, the currently
checked out branch is used.
Assume the following history exists and the current branch is "topic": Assume the following history exists and the current branch is "topic":
------------ ------------
@ -142,7 +148,7 @@ file you edit, you need to tell git that the conflict has been resolved,
typically this would be done with typically this would be done with
git update-index <filename> git add <filename>
After resolving the conflict manually and updating the index with the After resolving the conflict manually and updating the index with the

Просмотреть файл

@ -13,6 +13,7 @@ SYNOPSIS
'git-remote' add <name> <url> 'git-remote' add <name> <url>
'git-remote' show <name> 'git-remote' show <name>
'git-remote' prune <name> 'git-remote' prune <name>
'git-remote' update [group]
DESCRIPTION DESCRIPTION
----------- -----------
@ -31,6 +32,19 @@ subcommands are available to perform operations on the remotes.
Adds a remote named <name> for the repository at Adds a remote named <name> for the repository at
<url>. The command `git fetch <name>` can then be used to create and <url>. The command `git fetch <name>` can then be used to create and
update remote-tracking branches <name>/<branch>. update remote-tracking branches <name>/<branch>.
+
With `-f` option, `git fetch <name>` is run immediately after
the remote information is set up.
+
With `-t <branch>` option, instead of the default glob
refspec for the remote to track all branches under
`$GIT_DIR/remotes/<name>/`, a refspec to track only `<branch>`
is created. You can give more than one `-t <branch>` to track
multiple branche without grabbing all branches.
+
With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
up to point at remote's `<master>` branch instead of whatever
branch the `HEAD` at the remote repository actually points at.
'show':: 'show'::
@ -40,7 +54,17 @@ Gives some information about the remote <name>.
Deletes all stale tracking branches under <name>. Deletes all stale tracking branches under <name>.
These stale branches have already been removed from the remote repository These stale branches have already been removed from the remote repository
referenced by <name>, but are still locally available in "remotes/<name>". referenced by <name>, but are still locally available in
"remotes/<name>".
'update'::
Fetch updates for a named set of remotes in the repository as defined by
remotes.<group>. If a named group is not specified on the command line,
the configuration parameter remotes.default will get used; if
remotes.default is not defined, all remotes which do not the
configuration parameter remote.<name>.skipDefaultUpdate set to true will
be updated. (See gitlink:git-config[1]).
DISCUSSION DISCUSSION

Просмотреть файл

@ -163,8 +163,7 @@ If this three-way merge resolves cleanly, the result is written
out to your working tree file, so you would not have to manually out to your working tree file, so you would not have to manually
resolve it. Note that `git-rerere` leaves the index file alone, resolve it. Note that `git-rerere` leaves the index file alone,
so you still need to do the final sanity checks with `git diff` so you still need to do the final sanity checks with `git diff`
(or `git diff -c`) and `git update-index` when you are (or `git diff -c`) and `git add` when you are satisfied.
satisfied.
As a convenience measure, `git-merge` automatically invokes As a convenience measure, `git-merge` automatically invokes
`git-rerere` when it exits with a failed automerge, which `git-rerere` when it exits with a failed automerge, which

Просмотреть файл

@ -94,11 +94,11 @@ current HEAD.
<2> Rewind the master branch to get rid of those three commits. <2> Rewind the master branch to get rid of those three commits.
<3> Switch to "topic/wip" branch and keep working. <3> Switch to "topic/wip" branch and keep working.
Undo update-index:: Undo add::
+ +
------------ ------------
$ edit <1> $ edit <1>
$ git-update-index frotz.c filfre.c $ git add frotz.c filfre.c
$ mailx <2> $ mailx <2>
$ git reset <3> $ git reset <3>
$ git pull git://info.example.com/ nitfol <4> $ git pull git://info.example.com/ nitfol <4>

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -16,7 +16,7 @@ DESCRIPTION
Examines paths in the working tree that has changes unrecorded Examines paths in the working tree that has changes unrecorded
to the index file, and changes between the index file and the to the index file, and changes between the index file and the
current HEAD commit. The former paths are what you _could_ current HEAD commit. The former paths are what you _could_
commit by running 'git-update-index' before running 'git commit by running 'git add' (or 'git rm' if you are deleting) before running 'git
commit', and the latter paths are what you _would_ commit by commit', and the latter paths are what you _would_ commit by
running 'git commit'. running 'git commit'.

Просмотреть файл

@ -15,7 +15,7 @@ DESCRIPTION
Examines paths in the working tree that has changes unrecorded Examines paths in the working tree that has changes unrecorded
to the index file, and changes between the index file and the to the index file, and changes between the index file and the
current HEAD commit. The former paths are what you _could_ current HEAD commit. The former paths are what you _could_
commit by running 'git-update-index' before running 'git commit by running 'git add' before running 'git
commit', and the latter paths are what you _would_ commit by commit', and the latter paths are what you _would_ commit by
running 'git commit'. running 'git commit'.

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -25,15 +25,15 @@ mind.
an warning if the commit log message given to it does not look an warning if the commit log message given to it does not look
like a valid UTF-8 string, unless you explicitly say your like a valid UTF-8 string, unless you explicitly say your
project uses a legacy encoding. The way to say this is to project uses a legacy encoding. The way to say this is to
have core.commitencoding in `.git/config` file, like this: have i18n.commitencoding in `.git/config` file, like this:
+ +
------------ ------------
[core] [i18n]
commitencoding = ISO-8859-1 commitencoding = ISO-8859-1
------------ ------------
+ +
Commit objects created with the above setting record the value Commit objects created with the above setting record the value
of `core.commitencoding` in its `encoding` header. This is to of `i18n.commitencoding` in its `encoding` header. This is to
help other people who look at them later. Lack of this header help other people who look at them later. Lack of this header
implies that the commit log message is encoded in UTF-8. implies that the commit log message is encoded in UTF-8.
@ -41,15 +41,15 @@ implies that the commit log message is encoded in UTF-8.
header of a commit object, and tries to re-code the log header of a commit object, and tries to re-code the log
message into UTF-8 unless otherwise specified. You can message into UTF-8 unless otherwise specified. You can
specify the desired output encoding with specify the desired output encoding with
`core.logoutputencoding` in `.git/config` file, like this: `i18n.logoutputencoding` in `.git/config` file, like this:
+ +
------------ ------------
[core] [i18n]
logoutputencoding = ISO-8859-1 logoutputencoding = ISO-8859-1
------------ ------------
+ +
If you do not have this configuration variable, the value of If you do not have this configuration variable, the value of
`core.commitencoding` is used instead. `i18n.commitencoding` is used instead.
Note that we deliberately chose not to re-code the commit log Note that we deliberately chose not to re-code the commit log
message when a commit is made to force UTF-8 at the commit message when a commit is made to force UTF-8 at the commit

Просмотреть файл

@ -227,7 +227,7 @@ $ git diff
@@ -1 +1,2 @@ @@ -1 +1,2 @@
hello world! hello world!
+hello world, again +hello world, again
$ git update-index file.txt $ git add file.txt
$ git diff $ git diff
------------------------------------------------ ------------------------------------------------
@ -260,7 +260,7 @@ hello world!
hello world, again hello world, again
------------------------------------------------ ------------------------------------------------
So what our "git update-index" did was store a new blob and then put So what our "git add" did was store a new blob and then put
a reference to it in the index file. If we modify the file again, a reference to it in the index file. If we modify the file again,
we'll see that the new modifications are reflected in the "git-diff" we'll see that the new modifications are reflected in the "git-diff"
output: output:

Просмотреть файл

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

Просмотреть файл

@ -6,18 +6,19 @@ DEF_VER=v1.5.0.GIT
LF=' LF='
' '
# First try git-describe, then see if there is a version file # First see if there is a version file (included in release tarballs),
# (included in release tarballs), then default # then try git-describe, then default.
if VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && if test -f version
case "$VN" in
*$LF*) (exit 1) ;;
v[0-9]*) : happy ;;
esac
then
VN=$(echo "$VN" | sed -e 's/-/./g');
elif test -f version
then then
VN=$(cat version) || VN="$DEF_VER" VN=$(cat version) || VN="$DEF_VER"
elif test -d .git &&
VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
case "$VN" in
*$LF*) (exit 1) ;;
v[0-9]*) : happy ;;
esac
then
VN=$(echo "$VN" | sed -e 's/-/./g');
else else
VN="$DEF_VER" VN="$DEF_VER"
fi fi

Просмотреть файл

@ -28,6 +28,10 @@ all::
# #
# Define NO_STRLCPY if you don't have strlcpy. # Define NO_STRLCPY if you don't have strlcpy.
# #
# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
# If your compiler also does not support long long or does not have
# strtoull, define NO_STRTOULL.
#
# Define NO_SETENV if you don't have setenv in the C library. # Define NO_SETENV if you don't have setenv in the C library.
# #
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link. # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
@ -124,6 +128,7 @@ prefix = $(HOME)
bindir = $(prefix)/bin bindir = $(prefix)/bin
gitexecdir = $(bindir) gitexecdir = $(bindir)
template_dir = $(prefix)/share/git-core/templates/ template_dir = $(prefix)/share/git-core/templates/
ETC_GITCONFIG = $(prefix)/etc/gitconfig
# DESTDIR= # DESTDIR=
# default configuration for gitweb # default configuration for gitweb
@ -172,7 +177,7 @@ SCRIPT_SH = \
git-merge-one-file.sh git-parse-remote.sh \ git-merge-one-file.sh git-parse-remote.sh \
git-pull.sh git-rebase.sh \ git-pull.sh git-rebase.sh \
git-repack.sh git-request-pull.sh git-reset.sh \ git-repack.sh git-request-pull.sh git-reset.sh \
git-resolve.sh git-revert.sh git-sh-setup.sh \ git-revert.sh git-sh-setup.sh \
git-tag.sh git-verify-tag.sh \ git-tag.sh git-verify-tag.sh \
git-applymbox.sh git-applypatch.sh git-am.sh \ git-applymbox.sh git-applypatch.sh git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \ git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
@ -262,7 +267,8 @@ LIB_OBJS = \
revision.o pager.o tree-walk.o xdiff-interface.o \ revision.o pager.o tree-walk.o xdiff-interface.o \
write_or_die.o trace.o list-objects.o grep.o \ write_or_die.o trace.o list-objects.o grep.o \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o
BUILTIN_OBJS = \ BUILTIN_OBJS = \
builtin-add.o \ builtin-add.o \
@ -280,7 +286,6 @@ BUILTIN_OBJS = \
builtin-diff.o \ builtin-diff.o \
builtin-diff-files.o \ builtin-diff-files.o \
builtin-diff-index.o \ builtin-diff-index.o \
builtin-diff-stages.o \
builtin-diff-tree.o \ builtin-diff-tree.o \
builtin-fetch--tool.o \ builtin-fetch--tool.o \
builtin-fmt-merge-msg.o \ builtin-fmt-merge-msg.o \
@ -293,6 +298,7 @@ BUILTIN_OBJS = \
builtin-ls-tree.o \ builtin-ls-tree.o \
builtin-mailinfo.o \ builtin-mailinfo.o \
builtin-mailsplit.o \ builtin-mailsplit.o \
builtin-merge-base.o \
builtin-merge-file.o \ builtin-merge-file.o \
builtin-mv.o \ builtin-mv.o \
builtin-name-rev.o \ builtin-name-rev.o \
@ -354,11 +360,13 @@ ifeq ($(uname_S),SunOS)
NO_UNSETENV = YesPlease NO_UNSETENV = YesPlease
NO_SETENV = YesPlease NO_SETENV = YesPlease
NO_C99_FORMAT = YesPlease NO_C99_FORMAT = YesPlease
NO_STRTOUMAX = YesPlease
endif endif
ifeq ($(uname_R),5.9) ifeq ($(uname_R),5.9)
NO_UNSETENV = YesPlease NO_UNSETENV = YesPlease
NO_SETENV = YesPlease NO_SETENV = YesPlease
NO_C99_FORMAT = YesPlease NO_C99_FORMAT = YesPlease
NO_STRTOUMAX = YesPlease
endif endif
INSTALL = ginstall INSTALL = ginstall
TAR = gtar TAR = gtar
@ -518,6 +526,13 @@ ifdef NO_STRLCPY
COMPAT_CFLAGS += -DNO_STRLCPY COMPAT_CFLAGS += -DNO_STRLCPY
COMPAT_OBJS += compat/strlcpy.o COMPAT_OBJS += compat/strlcpy.o
endif endif
ifdef NO_STRTOUMAX
COMPAT_CFLAGS += -DNO_STRTOUMAX
COMPAT_OBJS += compat/strtoumax.o
endif
ifdef NO_STRTOULL
COMPAT_CFLAGS += -DNO_STRTOULL
endif
ifdef NO_SETENV ifdef NO_SETENV
COMPAT_CFLAGS += -DNO_SETENV COMPAT_CFLAGS += -DNO_SETENV
COMPAT_OBJS += compat/setenv.o COMPAT_OBJS += compat/setenv.o
@ -585,6 +600,7 @@ endif
# Shell quote (do not use $(call) to accommodate ancient setups); # Shell quote (do not use $(call) to accommodate ancient setups);
SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER)) SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG))
DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
bindir_SQ = $(subst ','\'',$(bindir)) bindir_SQ = $(subst ','\'',$(bindir))
@ -597,7 +613,8 @@ PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
LIBS = $(GITLIBS) $(EXTLIBS) LIBS = $(GITLIBS) $(EXTLIBS)
BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' $(COMPAT_CFLAGS) BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
-DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' $(COMPAT_CFLAGS)
LIB_OBJS += $(COMPAT_OBJS) LIB_OBJS += $(COMPAT_OBJS)
ALL_CFLAGS += $(BASIC_CFLAGS) ALL_CFLAGS += $(BASIC_CFLAGS)
@ -813,7 +830,7 @@ GIT-CFLAGS: .FORCE-GIT-CFLAGS
export NO_SVN_TESTS export NO_SVN_TESTS
test: all test: all test-chmtime$X
$(MAKE) -C t/ all $(MAKE) -C t/ all
test-date$X: test-date.c date.o ctype.o test-date$X: test-date.c date.o ctype.o
@ -828,6 +845,9 @@ test-dump-cache-tree$X: dump-cache-tree.o $(GITLIBS)
test-sha1$X: test-sha1.o $(GITLIBS) test-sha1$X: test-sha1.o $(GITLIBS)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
test-chmtime$X: test-chmtime.c
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $<
check-sha1:: test-sha1$X check-sha1:: test-sha1$X
./test-sha1.sh ./test-sha1.sh
@ -883,7 +903,8 @@ dist: git.spec git-archive
$(TAR) rf $(GIT_TARNAME).tar \ $(TAR) rf $(GIT_TARNAME).tar \
$(GIT_TARNAME)/git.spec \ $(GIT_TARNAME)/git.spec \
$(GIT_TARNAME)/version \ $(GIT_TARNAME)/version \
$(GIT_TARNAME)/git-gui/version $(GIT_TARNAME)/git-gui/version \
$(GIT_TARNAME)/git-gui/credits
@rm -rf $(GIT_TARNAME) @rm -rf $(GIT_TARNAME)
gzip -f -9 $(GIT_TARNAME).tar gzip -f -9 $(GIT_TARNAME).tar
@ -940,11 +961,14 @@ check-docs::
case "$$v" in \ case "$$v" in \
git-merge-octopus | git-merge-ours | git-merge-recursive | \ git-merge-octopus | git-merge-ours | git-merge-recursive | \
git-merge-resolve | git-merge-stupid | \ git-merge-resolve | git-merge-stupid | \
git-add--interactive | git-fsck-objects | git-init-db | \
git-repo-config | \
git-ssh-pull | git-ssh-push ) continue ;; \ git-ssh-pull | git-ssh-push ) continue ;; \
esac ; \ esac ; \
test -f "Documentation/$$v.txt" || \ test -f "Documentation/$$v.txt" || \
echo "no doc: $$v"; \ echo "no doc: $$v"; \
grep -q "^gitlink:$$v\[[0-9]\]::" Documentation/git.txt || \ sed -e '1,/^__DATA__/d' Documentation/cmd-list.perl | \
grep -q "^$$v[ ]" || \
case "$$v" in \ case "$$v" in \
git) ;; \ git) ;; \
*) echo "no link: $$v";; \ *) echo "no link: $$v";; \

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

6
blob.c
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -87,9 +87,9 @@ struct origin {
static char *fill_origin_blob(struct origin *o, mmfile_t *file) static char *fill_origin_blob(struct origin *o, mmfile_t *file)
{ {
if (!o->file.ptr) { if (!o->file.ptr) {
char type[10]; enum object_type type;
num_read_blob++; num_read_blob++;
file->ptr = read_sha1_file(o->blob_sha1, type, file->ptr = read_sha1_file(o->blob_sha1, &type,
(unsigned long *)(&(file->size))); (unsigned long *)(&(file->size)));
o->file = *file; o->file = *file;
} }
@ -263,7 +263,6 @@ static struct origin *get_origin(struct scoreboard *sb,
static int fill_blob_sha1(struct origin *origin) static int fill_blob_sha1(struct origin *origin)
{ {
unsigned mode; unsigned mode;
char type[10];
if (!is_null_sha1(origin->blob_sha1)) if (!is_null_sha1(origin->blob_sha1))
return 0; return 0;
@ -271,8 +270,7 @@ static int fill_blob_sha1(struct origin *origin)
origin->path, origin->path,
origin->blob_sha1, &mode)) origin->blob_sha1, &mode))
goto error_out; goto error_out;
if (sha1_object_info(origin->blob_sha1, type, NULL) || if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB)
strcmp(type, blob_type))
goto error_out; goto error_out;
return 0; return 0;
error_out: error_out:
@ -1322,10 +1320,10 @@ static void get_commit_info(struct commit *commit,
* we now need to populate them for output. * we now need to populate them for output.
*/ */
if (!commit->buffer) { if (!commit->buffer) {
char type[20]; enum object_type type;
unsigned long size; unsigned long size;
commit->buffer = commit->buffer =
read_sha1_file(commit->object.sha1, type, &size); read_sha1_file(commit->object.sha1, &type, &size);
} }
ret->author = author_buf; ret->author = author_buf;
get_ac_line(commit->buffer, "\nauthor ", get_ac_line(commit->buffer, "\nauthor ",
@ -2006,7 +2004,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
buf[fin_size] = 0; buf[fin_size] = 0;
origin->file.ptr = buf; origin->file.ptr = buf;
origin->file.size = fin_size; origin->file.size = fin_size;
pretend_sha1_file(buf, fin_size, blob_type, origin->blob_sha1); pretend_sha1_file(buf, fin_size, OBJ_BLOB, origin->blob_sha1);
commit->util = origin; commit->util = origin;
/* /*
@ -2065,9 +2063,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
int i, seen_dashdash, unk, opt; int i, seen_dashdash, unk, opt;
long bottom, top, lno; long bottom, top, lno;
int output_option = 0; int output_option = 0;
int show_stats = 0;
const char *revs_file = NULL; const char *revs_file = NULL;
const char *final_commit_name = NULL; const char *final_commit_name = NULL;
char type[10]; enum object_type type;
const char *bottomtop = NULL; const char *bottomtop = NULL;
const char *contents_from = NULL; const char *contents_from = NULL;
@ -2086,6 +2085,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
blank_boundary = 1; blank_boundary = 1;
else if (!strcmp("--root", arg)) else if (!strcmp("--root", arg))
show_root = 1; show_root = 1;
else if (!strcmp(arg, "--show-stats"))
show_stats = 1;
else if (!strcmp("-c", arg)) else if (!strcmp("-c", arg))
output_option |= OUTPUT_ANNOTATE_COMPAT; output_option |= OUTPUT_ANNOTATE_COMPAT;
else if (!strcmp("-t", arg)) else if (!strcmp("-t", arg))
@ -2094,17 +2095,17 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
output_option |= OUTPUT_LONG_OBJECT_NAME; output_option |= OUTPUT_LONG_OBJECT_NAME;
else if (!strcmp("-S", arg) && ++i < argc) else if (!strcmp("-S", arg) && ++i < argc)
revs_file = argv[i]; revs_file = argv[i];
else if (!strncmp("-M", arg, 2)) { else if (!prefixcmp(arg, "-M")) {
opt |= PICKAXE_BLAME_MOVE; opt |= PICKAXE_BLAME_MOVE;
blame_move_score = parse_score(arg+2); blame_move_score = parse_score(arg+2);
} }
else if (!strncmp("-C", arg, 2)) { else if (!prefixcmp(arg, "-C")) {
if (opt & PICKAXE_BLAME_COPY) if (opt & PICKAXE_BLAME_COPY)
opt |= PICKAXE_BLAME_COPY_HARDER; opt |= PICKAXE_BLAME_COPY_HARDER;
opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE; opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
blame_copy_score = parse_score(arg+2); blame_copy_score = parse_score(arg+2);
} }
else if (!strncmp("-L", arg, 2)) { else if (!prefixcmp(arg, "-L")) {
if (!arg[2]) { if (!arg[2]) {
if (++i >= argc) if (++i >= argc)
usage(blame_usage); usage(blame_usage);
@ -2200,6 +2201,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
if (!strcmp(argv[j], "--")) if (!strcmp(argv[j], "--"))
seen_dashdash = j; seen_dashdash = j;
if (seen_dashdash) { if (seen_dashdash) {
/* (2) */
if (seen_dashdash + 1 != argc - 1) if (seen_dashdash + 1 != argc - 1)
usage(blame_usage); usage(blame_usage);
path = add_prefix(prefix, argv[seen_dashdash + 1]); path = add_prefix(prefix, argv[seen_dashdash + 1]);
@ -2208,6 +2210,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
} }
else { else {
/* (3) */ /* (3) */
if (argc <= i)
usage(blame_usage);
path = add_prefix(prefix, argv[i]); path = add_prefix(prefix, argv[i]);
if (i + 1 == argc - 1) { if (i + 1 == argc - 1) {
final_commit_name = argv[i + 1]; final_commit_name = argv[i + 1];
@ -2296,7 +2300,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
if (fill_blob_sha1(o)) if (fill_blob_sha1(o))
die("no such path %s in %s", path, final_commit_name); die("no such path %s in %s", path, final_commit_name);
sb.final_buf = read_sha1_file(o->blob_sha1, type, sb.final_buf = read_sha1_file(o->blob_sha1, &type,
&sb.final_buf_size); &sb.final_buf_size);
} }
num_read_blob++; num_read_blob++;
@ -2348,7 +2352,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
ent = e; ent = e;
} }
if (DEBUG) { if (show_stats) {
printf("num read blob: %d\n", num_read_blob); printf("num read blob: %d\n", num_read_blob);
printf("num get patch: %d\n", num_get_patch); printf("num get patch: %d\n", num_get_patch);
printf("num commits: %d\n", num_commits); printf("num commits: %d\n", num_commits);

Просмотреть файл

@ -59,7 +59,7 @@ int git_branch_config(const char *var, const char *value)
branch_use_color = git_config_colorbool(var, value); branch_use_color = git_config_colorbool(var, value);
return 0; return 0;
} }
if (!strncmp(var, "color.branch.", 13)) { if (!prefixcmp(var, "color.branch.")) {
int slot = parse_branch_color_slot(var, 13); int slot = parse_branch_color_slot(var, 13);
color_parse(value, var, branch_colors[slot]); color_parse(value, var, branch_colors[slot]);
return 0; return 0;
@ -134,7 +134,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
*/ */
if (!force && if (!force &&
!in_merge_bases(rev, head_rev)) { !in_merge_bases(rev, &head_rev, 1)) {
error("The branch '%s' is not a strict subset of " error("The branch '%s' is not a strict subset of "
"your current HEAD.\n" "your current HEAD.\n"
"If you are sure you want to delete it, " "If you are sure you want to delete it, "
@ -178,13 +178,13 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
int len; int len;
/* Detect kind */ /* Detect kind */
if (!strncmp(refname, "refs/heads/", 11)) { if (!prefixcmp(refname, "refs/heads/")) {
kind = REF_LOCAL_BRANCH; kind = REF_LOCAL_BRANCH;
refname += 11; refname += 11;
} else if (!strncmp(refname, "refs/remotes/", 13)) { } else if (!prefixcmp(refname, "refs/remotes/")) {
kind = REF_REMOTE_BRANCH; kind = REF_REMOTE_BRANCH;
refname += 13; refname += 13;
} else if (!strncmp(refname, "refs/tags/", 10)) { } else if (!prefixcmp(refname, "refs/tags/")) {
kind = REF_TAG; kind = REF_TAG;
refname += 10; refname += 10;
} }
@ -446,7 +446,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
reflog = 1; reflog = 1;
continue; continue;
} }
if (!strncmp(arg, "--abbrev=", 9)) { if (!prefixcmp(arg, "--abbrev=")) {
abbrev = atoi(arg+9); abbrev = atoi(arg+9);
continue; continue;
} }
@ -476,7 +476,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
detached = 1; detached = 1;
} }
else { else {
if (strncmp(head, "refs/heads/", 11)) if (prefixcmp(head, "refs/heads/"))
die("HEAD not found below refs/heads!"); die("HEAD not found below refs/heads!");
head += 11; head += 11;
} }

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -47,11 +47,10 @@ static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...)
static void check_valid(unsigned char *sha1, const char *expect) static void check_valid(unsigned char *sha1, const char *expect)
{ {
char type[20]; enum object_type type = sha1_object_info(sha1, NULL);
if (type < 0)
if (sha1_object_info(sha1, type, NULL))
die("%s is not a valid object", sha1_to_hex(sha1)); die("%s is not a valid object", sha1_to_hex(sha1));
if (expect && strcmp(type, expect)) if (expect && type != type_from_string(expect))
die("%s is not a valid '%s' object", sha1_to_hex(sha1), die("%s is not a valid '%s' object", sha1_to_hex(sha1),
expect); expect);
} }

Просмотреть файл

@ -64,7 +64,7 @@ static int get_value(const char* key_, const char* regex_)
int ret = -1; int ret = -1;
char *tl; char *tl;
char *global = NULL, *repo_config = NULL; char *global = NULL, *repo_config = NULL;
const char *local; const char *system_wide = NULL, *local;
local = getenv(CONFIG_ENVIRONMENT); local = getenv(CONFIG_ENVIRONMENT);
if (!local) { if (!local) {
@ -74,6 +74,7 @@ static int get_value(const char* key_, const char* regex_)
local = repo_config = xstrdup(git_path("config")); local = repo_config = xstrdup(git_path("config"));
if (home) if (home)
global = xstrdup(mkpath("%s/.gitconfig", home)); global = xstrdup(mkpath("%s/.gitconfig", home));
system_wide = ETC_GITCONFIG;
} }
key = xstrdup(key_); key = xstrdup(key_);
@ -103,11 +104,15 @@ static int get_value(const char* key_, const char* regex_)
} }
} }
if (do_all && system_wide)
git_config_from_file(show_config, system_wide);
if (do_all && global) if (do_all && global)
git_config_from_file(show_config, global); git_config_from_file(show_config, global);
git_config_from_file(show_config, local); git_config_from_file(show_config, local);
if (!do_all && !seen && global) if (!do_all && !seen && global)
git_config_from_file(show_config, global); git_config_from_file(show_config, global);
if (!do_all && !seen && system_wide)
git_config_from_file(show_config, system_wide);
free(key); free(key);
if (regexp) { if (regexp) {
@ -147,7 +152,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)
} else { } else {
die("$HOME not set"); die("$HOME not set");
} }
} else if (!strcmp(argv[1], "--rename-section")) { }
else if (!strcmp(argv[1], "--system"))
setenv("GIT_CONFIG", ETC_GITCONFIG, 1);
else if (!strcmp(argv[1], "--rename-section")) {
int ret; int ret;
if (argc != 4) if (argc != 4)
usage(git_config_set_usage); usage(git_config_set_usage);
@ -159,7 +167,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
return 1; return 1;
} }
return 0; return 0;
} else }
else
break; break;
argc--; argc--;
argv++; argv++;

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -192,7 +192,8 @@ static int builtin_diff_combined(struct rev_info *revs,
parent = xmalloc(ents * sizeof(*parent)); parent = xmalloc(ents * sizeof(*parent));
/* Again, the revs are all reverse */ /* Again, the revs are all reverse */
for (i = 0; i < ents; i++) for (i = 0; i < ents; i++)
hashcpy((unsigned char*)parent + i, ent[ents - 1 - i].item->sha1); hashcpy((unsigned char *)(parent + i),
ent[ents - 1 - i].item->sha1);
diff_tree_combined(parent[0], parent + 1, ents - 1, diff_tree_combined(parent[0], parent + 1, ents - 1,
revs->dense_combined_merges, revs); revs->dense_combined_merges, revs);
return 0; return 0;
@ -260,6 +261,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
break; break;
else if (!strcmp(arg, "--cached")) { else if (!strcmp(arg, "--cached")) {
add_head(&rev); add_head(&rev);
if (!rev.pending.nr)
die("No HEAD commit to compare with (yet)");
break; break;
} }
} }

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -546,7 +546,7 @@ static int fsck_head_link(void)
if (!head_points_at || !(flag & REF_ISSYMREF)) if (!head_points_at || !(flag & REF_ISSYMREF))
return error("HEAD is not a symbolic ref"); return error("HEAD is not a symbolic ref");
if (strncmp(head_points_at, "refs/heads/", 11)) if (prefixcmp(head_points_at, "refs/heads/"))
return error("HEAD points to something strange (%s)", return error("HEAD points to something strange (%s)",
head_points_at); head_points_at);
if (is_null_sha1(sha1)) if (is_null_sha1(sha1))

Просмотреть файл

@ -84,11 +84,11 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char
{ {
unsigned long size; unsigned long size;
char *data; char *data;
char type[20]; enum object_type type;
char *to_free = NULL; char *to_free = NULL;
int hit; int hit;
data = read_sha1_file(sha1, type, &size); data = read_sha1_file(sha1, &type, &size);
if (!data) { if (!data) {
error("'%s': unable to read %s", name, sha1_to_hex(sha1)); error("'%s': unable to read %s", name, sha1_to_hex(sha1));
return 0; return 0;
@ -380,10 +380,10 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
else if (S_ISREG(entry.mode)) else if (S_ISREG(entry.mode))
hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len); hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len);
else if (S_ISDIR(entry.mode)) { else if (S_ISDIR(entry.mode)) {
char type[20]; enum object_type type;
struct tree_desc sub; struct tree_desc sub;
void *data; void *data;
data = read_sha1_file(entry.sha1, type, &sub.size); data = read_sha1_file(entry.sha1, &type, &sub.size);
if (!data) if (!data)
die("unable to read tree (%s)", die("unable to read tree (%s)",
sha1_to_hex(entry.sha1)); sha1_to_hex(entry.sha1));
@ -527,9 +527,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.word_regexp = 1; opt.word_regexp = 1;
continue; continue;
} }
if (!strncmp("-A", arg, 2) || if (!prefixcmp(arg, "-A") ||
!strncmp("-B", arg, 2) || !prefixcmp(arg, "-B") ||
!strncmp("-C", arg, 2) || !prefixcmp(arg, "-C") ||
(arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) { (arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) {
unsigned num; unsigned num;
const char *scan; const char *scan;

Просмотреть файл

@ -283,11 +283,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++, argv++) { for (i = 1; i < argc; i++, argv++) {
const char *arg = argv[1]; const char *arg = argv[1];
if (!strncmp(arg, "--template=", 11)) if (!prefixcmp(arg, "--template="))
template_dir = arg+11; template_dir = arg+11;
else if (!strcmp(arg, "--shared")) else if (!strcmp(arg, "--shared"))
shared_repository = PERM_GROUP; shared_repository = PERM_GROUP;
else if (!strncmp(arg, "--shared=", 9)) else if (!prefixcmp(arg, "--shared="))
shared_repository = git_config_perm("arg", arg+9); shared_repository = git_config_perm("arg", arg+9);
else else
usage(init_db_usage); usage(init_db_usage);

Просмотреть файл

@ -32,7 +32,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
rev->always_show_header = 0; rev->always_show_header = 0;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
const char *arg = argv[i]; const char *arg = argv[i];
if (!strncmp(arg, "--encoding=", 11)) { if (!prefixcmp(arg, "--encoding=")) {
arg += 11; arg += 11;
if (strcmp(arg, "none")) if (strcmp(arg, "none"))
git_log_output_encoding = strdup(arg); git_log_output_encoding = strdup(arg);
@ -89,8 +89,8 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
static int show_object(const unsigned char *sha1, int suppress_header) static int show_object(const unsigned char *sha1, int suppress_header)
{ {
unsigned long size; unsigned long size;
char type[20]; enum object_type type;
char *buf = read_sha1_file(sha1, type, &size); char *buf = read_sha1_file(sha1, &type, &size);
int offset = 0; int offset = 0;
if (!buf) if (!buf)
@ -224,6 +224,9 @@ int cmd_log(int argc, const char **argv, const char *prefix)
return cmd_log_walk(&rev); return cmd_log_walk(&rev);
} }
/* format-patch */
#define FORMAT_PATCH_NAME_MAX 64
static int istitlechar(char c) static int istitlechar(char c)
{ {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
@ -264,15 +267,18 @@ static int git_format_config(const char *var, const char *value)
static FILE *realstdout = NULL; static FILE *realstdout = NULL;
static const char *output_directory = NULL; static const char *output_directory = NULL;
static void reopen_stdout(struct commit *commit, int nr, int keep_subject) static int reopen_stdout(struct commit *commit, int nr, int keep_subject)
{ {
char filename[1024]; char filename[PATH_MAX];
char *sol; char *sol;
int len = 0; int len = 0;
int suffix_len = strlen(fmt_patch_suffix) + 10; /* ., NUL and slop */ int suffix_len = strlen(fmt_patch_suffix) + 1;
if (output_directory) { if (output_directory) {
strlcpy(filename, output_directory, 1000); if (strlen(output_directory) >=
sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len)
return error("name of output directory is too long");
strlcpy(filename, output_directory, sizeof(filename) - suffix_len);
len = strlen(filename); len = strlen(filename);
if (filename[len - 1] != '/') if (filename[len - 1] != '/')
filename[len++] = '/'; filename[len++] = '/';
@ -287,7 +293,7 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject)
sol += 2; sol += 2;
/* strip [PATCH] or [PATCH blabla] */ /* strip [PATCH] or [PATCH blabla] */
if (!keep_subject && !strncmp(sol, "[PATCH", 6)) { if (!keep_subject && !prefixcmp(sol, "[PATCH")) {
char *eos = strchr(sol + 6, ']'); char *eos = strchr(sol + 6, ']');
if (eos) { if (eos) {
while (isspace(*eos)) while (isspace(*eos))
@ -297,7 +303,8 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject)
} }
for (j = 0; for (j = 0;
len < sizeof(filename) - suffix_len && j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 &&
len < sizeof(filename) - suffix_len &&
sol[j] && sol[j] != '\n'; sol[j] && sol[j] != '\n';
j++) { j++) {
if (istitlechar(sol[j])) { if (istitlechar(sol[j])) {
@ -314,10 +321,16 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject)
} }
while (filename[len - 1] == '.' || filename[len - 1] == '-') while (filename[len - 1] == '.' || filename[len - 1] == '-')
len--; len--;
filename[len] = 0;
} }
if (len + suffix_len >= sizeof(filename))
return error("Patch pathname too long");
strcpy(filename + len, fmt_patch_suffix); strcpy(filename + len, fmt_patch_suffix);
fprintf(realstdout, "%s\n", filename); fprintf(realstdout, "%s\n", filename);
freopen(filename, "w", stdout); if (freopen(filename, "w", stdout) == NULL)
return error("Cannot open patch file %s",filename);
return 0;
} }
static int get_patch_id(struct commit *commit, struct diff_options *options, static int get_patch_id(struct commit *commit, struct diff_options *options,
@ -435,7 +448,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
else if (!strcmp(argv[i], "-n") || else if (!strcmp(argv[i], "-n") ||
!strcmp(argv[i], "--numbered")) !strcmp(argv[i], "--numbered"))
numbered = 1; numbered = 1;
else if (!strncmp(argv[i], "--start-number=", 15)) else if (!prefixcmp(argv[i], "--start-number="))
start_number = strtol(argv[i] + 15, NULL, 10); start_number = strtol(argv[i] + 15, NULL, 10);
else if (!strcmp(argv[i], "--start-number")) { else if (!strcmp(argv[i], "--start-number")) {
i++; i++;
@ -471,13 +484,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
} }
else if (!strcmp(argv[i], "--attach")) else if (!strcmp(argv[i], "--attach"))
rev.mime_boundary = git_version_string; rev.mime_boundary = git_version_string;
else if (!strncmp(argv[i], "--attach=", 9)) else if (!prefixcmp(argv[i], "--attach="))
rev.mime_boundary = argv[i] + 9; rev.mime_boundary = argv[i] + 9;
else if (!strcmp(argv[i], "--ignore-if-in-upstream")) else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
ignore_if_in_upstream = 1; ignore_if_in_upstream = 1;
else if (!strcmp(argv[i], "--thread")) else if (!strcmp(argv[i], "--thread"))
thread = 1; thread = 1;
else if (!strncmp(argv[i], "--in-reply-to=", 14)) else if (!prefixcmp(argv[i], "--in-reply-to="))
in_reply_to = argv[i] + 14; in_reply_to = argv[i] + 14;
else if (!strcmp(argv[i], "--in-reply-to")) { else if (!strcmp(argv[i], "--in-reply-to")) {
i++; i++;
@ -485,7 +498,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
die("Need a Message-Id for --in-reply-to"); die("Need a Message-Id for --in-reply-to");
in_reply_to = argv[i]; in_reply_to = argv[i];
} }
else if (!strncmp(argv[i], "--suffix=", 9)) else if (!prefixcmp(argv[i], "--suffix="))
fmt_patch_suffix = argv[i] + 9; fmt_patch_suffix = argv[i] + 9;
else else
argv[j++] = argv[i]; argv[j++] = argv[i];
@ -573,7 +586,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.message_id = message_id; rev.message_id = message_id;
} }
if (!use_stdout) if (!use_stdout)
reopen_stdout(commit, rev.nr, keep_subject); if (reopen_stdout(commit, rev.nr, keep_subject))
die("Failed to create output files");
shown = log_tree_commit(&rev, commit); shown = log_tree_commit(&rev, commit);
free(commit->buffer); free(commit->buffer);
commit->buffer = NULL; commit->buffer = NULL;

Просмотреть файл

@ -406,7 +406,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]); add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]);
continue; continue;
} }
if (!strncmp(arg, "--exclude=", 10)) { if (!prefixcmp(arg, "--exclude=")) {
exc_given = 1; exc_given = 1;
add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]); add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]);
continue; continue;
@ -416,12 +416,12 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
add_excludes_from_file(&dir, argv[++i]); add_excludes_from_file(&dir, argv[++i]);
continue; continue;
} }
if (!strncmp(arg, "--exclude-from=", 15)) { if (!prefixcmp(arg, "--exclude-from=")) {
exc_given = 1; exc_given = 1;
add_excludes_from_file(&dir, arg+15); add_excludes_from_file(&dir, arg+15);
continue; continue;
} }
if (!strncmp(arg, "--exclude-per-directory=", 24)) { if (!prefixcmp(arg, "--exclude-per-directory=")) {
exc_given = 1; exc_given = 1;
dir.exclude_per_dir = arg + 24; dir.exclude_per_dir = arg + 24;
continue; continue;
@ -434,7 +434,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
error_unmatch = 1; error_unmatch = 1;
continue; continue;
} }
if (!strncmp(arg, "--abbrev=", 9)) { if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg+9, NULL, 10); abbrev = strtoul(arg+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV) if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV; abbrev = MINIMUM_ABBREV;

Просмотреть файл

@ -118,7 +118,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
chomp_prefix = 0; chomp_prefix = 0;
break; break;
} }
if (!strncmp(argv[1]+2, "abbrev=",7)) { if (!prefixcmp(argv[1]+2, "abbrev=")) {
abbrev = strtoul(argv[1]+9, NULL, 10); abbrev = strtoul(argv[1]+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV) if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV; abbrev = MINIMUM_ABBREV;

Просмотреть файл

@ -406,6 +406,11 @@ static int is_rfc2822_header(char *line)
*/ */
int ch; int ch;
char *cp = line; char *cp = line;
/* Count mbox From headers as headers */
if (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6))
return 1;
while ((ch = *cp++)) { while ((ch = *cp++)) {
if (ch == ':') if (ch == ':')
return cp != line; return cp != line;
@ -417,30 +422,61 @@ static int is_rfc2822_header(char *line)
return 0; return 0;
} }
/*
* sz is size of 'line' buffer in bytes. Must be reasonably
* long enough to hold one physical real-world e-mail line.
*/
static int read_one_header_line(char *line, int sz, FILE *in) static int read_one_header_line(char *line, int sz, FILE *in)
{ {
int ofs = 0; int len;
while (ofs < sz) {
int peek, len; /*
if (fgets(line + ofs, sz - ofs, in) == NULL) * We will read at most (sz-1) bytes and then potentially
break; * re-add NUL after it. Accessing line[sz] after this is safe
len = eatspace(line + ofs); * and we can allow len to grow up to and including sz.
if ((len == 0) || !is_rfc2822_header(line)) { */
/* Re-add the newline */ sz--;
line[ofs + len] = '\n';
line[ofs + len + 1] = '\0'; /* Get the first part of the line. */
break; if (!fgets(line, sz, in))
} return 0;
ofs += len;
/* Yuck, 2822 header "folding" */ /*
* Is it an empty line or not a valid rfc2822 header?
* If so, stop here, and return false ("not a header")
*/
len = eatspace(line);
if (!len || !is_rfc2822_header(line)) {
/* Re-add the newline */
line[len] = '\n';
line[len + 1] = '\0';
return 0;
}
/*
* Now we need to eat all the continuation lines..
* Yuck, 2822 header "folding"
*/
for (;;) {
int peek, addlen;
static char continuation[1000];
peek = fgetc(in); ungetc(peek, in); peek = fgetc(in); ungetc(peek, in);
if (peek != ' ' && peek != '\t') if (peek != ' ' && peek != '\t')
break; break;
if (!fgets(continuation, sizeof(continuation), in))
break;
addlen = eatspace(continuation);
if (len < sz - 1) {
if (addlen >= sz - len)
addlen = sz - len - 1;
memcpy(line + len, continuation, addlen);
len += addlen;
}
} }
/* Count mbox From headers as headers */ line[len] = 0;
if (!ofs && (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6)))
ofs = 1; return 1;
return ofs;
} }
static int decode_q_segment(char *in, char *ot, char *ep, int rfc2047) static int decode_q_segment(char *in, char *ot, char *ep, int rfc2047)
@ -811,7 +847,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
metainfo_charset = def_charset; metainfo_charset = def_charset;
else if (!strcmp(argv[1], "-n")) else if (!strcmp(argv[1], "-n"))
metainfo_charset = NULL; metainfo_charset = NULL;
else if (!strncmp(argv[1], "--encoding=", 11)) else if (!prefixcmp(argv[1], "--encoding="))
metainfo_charset = argv[1] + 11; metainfo_charset = argv[1] + 11;
else else
usage(mailinfo_usage); usage(mailinfo_usage);

Просмотреть файл

@ -1,9 +1,7 @@
#include "cache.h" #include "cache.h"
#include "commit.h" #include "commit.h"
static int show_all; static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_all)
static int merge_base(struct commit *rev1, struct commit *rev2)
{ {
struct commit_list *result = get_merge_bases(rev1, rev2, 0); struct commit_list *result = get_merge_bases(rev1, rev2, 0);
@ -23,16 +21,16 @@ static int merge_base(struct commit *rev1, struct commit *rev2)
static const char merge_base_usage[] = static const char merge_base_usage[] =
"git-merge-base [--all] <commit-id> <commit-id>"; "git-merge-base [--all] <commit-id> <commit-id>";
int main(int argc, char **argv) int cmd_merge_base(int argc, const char **argv, const char *prefix)
{ {
struct commit *rev1, *rev2; struct commit *rev1, *rev2;
unsigned char rev1key[20], rev2key[20]; unsigned char rev1key[20], rev2key[20];
int show_all = 0;
setup_git_directory();
git_config(git_default_config); git_config(git_default_config);
while (1 < argc && argv[1][0] == '-') { while (1 < argc && argv[1][0] == '-') {
char *arg = argv[1]; const char *arg = argv[1];
if (!strcmp(arg, "-a") || !strcmp(arg, "--all")) if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))
show_all = 1; show_all = 1;
else else
@ -49,5 +47,5 @@ int main(int argc, char **argv)
rev2 = lookup_commit_reference(rev2key); rev2 = lookup_commit_reference(rev2key);
if (!rev1 || !rev2) if (!rev1 || !rev2)
return 1; return 1;
return merge_base(rev1, rev2); return show_merge_base(rev1, rev2, show_all);
} }

Просмотреть файл

@ -5,7 +5,7 @@
#include "refs.h" #include "refs.h"
static const char name_rev_usage[] = static const char name_rev_usage[] =
"git-name-rev [--tags] ( --all | --stdin | committish [committish...] )\n"; "git-name-rev [--tags | --refs=<pattern>] ( --all | --stdin | committish [committish...] )\n";
typedef struct rev_name { typedef struct rev_name {
const char *tip_name; const char *tip_name;
@ -57,13 +57,17 @@ copy_data:
parents; parents;
parents = parents->next, parent_number++) { parents = parents->next, parent_number++) {
if (parent_number > 1) { if (parent_number > 1) {
char *new_name = xmalloc(strlen(tip_name)+8); int len = strlen(tip_name);
char *new_name = xmalloc(len + 8);
if (len > 2 && !strcmp(tip_name + len - 2, "^0"))
len -= 2;
if (generation > 0) if (generation > 0)
sprintf(new_name, "%s~%d^%d", tip_name, sprintf(new_name, "%.*s~%d^%d", len, tip_name,
generation, parent_number); generation, parent_number);
else else
sprintf(new_name, "%s^%d", tip_name, parent_number); sprintf(new_name, "%.*s^%d", len, tip_name,
parent_number);
name_rev(parents->item, new_name, name_rev(parents->item, new_name,
merge_traversals + 1 , 0, 0); merge_traversals + 1 , 0, 0);
@ -74,13 +78,21 @@ copy_data:
} }
} }
struct name_ref_data {
int tags_only;
const char *ref_filter;
};
static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data) static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data)
{ {
struct object *o = parse_object(sha1); struct object *o = parse_object(sha1);
int tags_only = *(int*)cb_data; struct name_ref_data *data = cb_data;
int deref = 0; int deref = 0;
if (tags_only && strncmp(path, "refs/tags/", 10)) if (data->tags_only && prefixcmp(path, "refs/tags/"))
return 0;
if (data->ref_filter && fnmatch(data->ref_filter, path, 0))
return 0; return 0;
while (o && o->type == OBJ_TAG) { while (o && o->type == OBJ_TAG) {
@ -93,9 +105,9 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void
if (o && o->type == OBJ_COMMIT) { if (o && o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o; struct commit *commit = (struct commit *)o;
if (!strncmp(path, "refs/heads/", 11)) if (!prefixcmp(path, "refs/heads/"))
path = path + 11; path = path + 11;
else if (!strncmp(path, "refs/", 5)) else if (!prefixcmp(path, "refs/"))
path = path + 5; path = path + 5;
name_rev(commit, xstrdup(path), 0, 0, deref); name_rev(commit, xstrdup(path), 0, 0, deref);
@ -119,17 +131,22 @@ static const char* get_rev_name(struct object *o)
if (!n->generation) if (!n->generation)
return n->tip_name; return n->tip_name;
else {
int len = strlen(n->tip_name);
if (len > 2 && !strcmp(n->tip_name + len - 2, "^0"))
len -= 2;
snprintf(buffer, sizeof(buffer), "%.*s~%d", len, n->tip_name,
n->generation);
snprintf(buffer, sizeof(buffer), "%s~%d", n->tip_name, n->generation); return buffer;
}
return buffer;
} }
int cmd_name_rev(int argc, const char **argv, const char *prefix) int cmd_name_rev(int argc, const char **argv, const char *prefix)
{ {
struct object_array revs = { 0, 0, NULL }; struct object_array revs = { 0, 0, NULL };
int as_is = 0, all = 0, transform_stdin = 0; int as_is = 0, all = 0, transform_stdin = 0;
int tags_only = 0; struct name_ref_data data = { 0, NULL };
git_config(git_default_config); git_config(git_default_config);
@ -146,7 +163,10 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
as_is = 1; as_is = 1;
continue; continue;
} else if (!strcmp(*argv, "--tags")) { } else if (!strcmp(*argv, "--tags")) {
tags_only = 1; data.tags_only = 1;
continue;
} else if (!prefixcmp(*argv, "--refs=")) {
data.ref_filter = *argv + 7;
continue; continue;
} else if (!strcmp(*argv, "--all")) { } else if (!strcmp(*argv, "--all")) {
if (argc > 1) if (argc > 1)
@ -185,7 +205,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
add_object_array((struct object *)commit, *argv, &revs); add_object_array((struct object *)commit, *argv, &revs);
} }
for_each_ref(name_ref, &tags_only); for_each_ref(name_ref, &data);
if (transform_stdin) { if (transform_stdin) {
char buffer[2048]; char buffer[2048];

Просмотреть файл

@ -230,8 +230,8 @@ static unsigned char *find_packed_object_name(struct packed_git *p,
static void *delta_against(void *buf, unsigned long size, struct object_entry *entry) static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
{ {
unsigned long othersize, delta_size; unsigned long othersize, delta_size;
char type[10]; enum object_type type;
void *otherbuf = read_sha1_file(entry->delta->sha1, type, &othersize); void *otherbuf = read_sha1_file(entry->delta->sha1, &type, &othersize);
void *delta_buf; void *delta_buf;
if (!otherbuf) if (!otherbuf)
@ -375,7 +375,7 @@ static unsigned long write_object(struct sha1file *f,
struct object_entry *entry) struct object_entry *entry)
{ {
unsigned long size; unsigned long size;
char type[10]; enum object_type type;
void *buf; void *buf;
unsigned char header[10]; unsigned char header[10];
unsigned hdrlen, datalen; unsigned hdrlen, datalen;
@ -416,7 +416,7 @@ static unsigned long write_object(struct sha1file *f,
} }
if (!to_reuse) { if (!to_reuse) {
buf = read_sha1_file(entry->sha1, type, &size); buf = read_sha1_file(entry->sha1, &type, &size);
if (!buf) if (!buf)
die("unable to read %s", sha1_to_hex(entry->sha1)); die("unable to read %s", sha1_to_hex(entry->sha1));
if (size != entry->size) if (size != entry->size)
@ -765,7 +765,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
struct pbase_tree_cache *ent, *nent; struct pbase_tree_cache *ent, *nent;
void *data; void *data;
unsigned long size; unsigned long size;
char type[20]; enum object_type type;
int neigh; int neigh;
int my_ix = pbase_tree_cache_ix(sha1); int my_ix = pbase_tree_cache_ix(sha1);
int available_ix = -1; int available_ix = -1;
@ -792,10 +792,10 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)
/* Did not find one. Either we got a bogus request or /* Did not find one. Either we got a bogus request or
* we need to read and perhaps cache. * we need to read and perhaps cache.
*/ */
data = read_sha1_file(sha1, type, &size); data = read_sha1_file(sha1, &type, &size);
if (!data) if (!data)
return NULL; return NULL;
if (strcmp(type, tree_type)) { if (type != OBJ_TREE) {
free(data); free(data);
return NULL; return NULL;
} }
@ -854,19 +854,19 @@ static void add_pbase_object(struct tree_desc *tree,
while (tree_entry(tree,&entry)) { while (tree_entry(tree,&entry)) {
unsigned long size; unsigned long size;
char type[20]; enum object_type type;
if (entry.pathlen != cmplen || if (entry.pathlen != cmplen ||
memcmp(entry.path, name, cmplen) || memcmp(entry.path, name, cmplen) ||
!has_sha1_file(entry.sha1) || !has_sha1_file(entry.sha1) ||
sha1_object_info(entry.sha1, type, &size)) (type = sha1_object_info(entry.sha1, &size)) < 0)
continue; continue;
if (name[cmplen] != '/') { if (name[cmplen] != '/') {
unsigned hash = name_hash(fullname); unsigned hash = name_hash(fullname);
add_object_entry(entry.sha1, hash, 1); add_object_entry(entry.sha1, hash, 1);
return; return;
} }
if (!strcmp(type, tree_type)) { if (type == OBJ_TREE) {
struct tree_desc sub; struct tree_desc sub;
struct pbase_tree_cache *tree; struct pbase_tree_cache *tree;
const char *down = name+cmplen+1; const char *down = name+cmplen+1;
@ -978,8 +978,6 @@ static void add_preferred_base(unsigned char *sha1)
static void check_object(struct object_entry *entry) static void check_object(struct object_entry *entry)
{ {
char type[20];
if (entry->in_pack && !entry->preferred_base) { if (entry->in_pack && !entry->preferred_base) {
struct packed_git *p = entry->in_pack; struct packed_git *p = entry->in_pack;
struct pack_window *w_curs = NULL; struct pack_window *w_curs = NULL;
@ -1062,21 +1060,10 @@ static void check_object(struct object_entry *entry)
/* Otherwise we would do the usual */ /* Otherwise we would do the usual */
} }
if (sha1_object_info(entry->sha1, type, &entry->size)) entry->type = sha1_object_info(entry->sha1, &entry->size);
if (entry->type < 0)
die("unable to get type of object %s", die("unable to get type of object %s",
sha1_to_hex(entry->sha1)); sha1_to_hex(entry->sha1));
if (!strcmp(type, commit_type)) {
entry->type = OBJ_COMMIT;
} else if (!strcmp(type, tree_type)) {
entry->type = OBJ_TREE;
} else if (!strcmp(type, blob_type)) {
entry->type = OBJ_BLOB;
} else if (!strcmp(type, tag_type)) {
entry->type = OBJ_TAG;
} else
die("unable to pack object %s of type %s",
sha1_to_hex(entry->sha1), type);
} }
static unsigned int check_delta_limit(struct object_entry *me, unsigned int n) static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
@ -1206,7 +1193,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
struct object_entry *trg_entry = trg->entry; struct object_entry *trg_entry = trg->entry;
struct object_entry *src_entry = src->entry; struct object_entry *src_entry = src->entry;
unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz; unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;
char type[10]; enum object_type type;
void *delta_buf; void *delta_buf;
/* Don't bother doing diffs between different types */ /* Don't bother doing diffs between different types */
@ -1257,13 +1244,13 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
/* Load data if not already done */ /* Load data if not already done */
if (!trg->data) { if (!trg->data) {
trg->data = read_sha1_file(trg_entry->sha1, type, &sz); trg->data = read_sha1_file(trg_entry->sha1, &type, &sz);
if (sz != trg_size) if (sz != trg_size)
die("object %s inconsistent object length (%lu vs %lu)", die("object %s inconsistent object length (%lu vs %lu)",
sha1_to_hex(trg_entry->sha1), sz, trg_size); sha1_to_hex(trg_entry->sha1), sz, trg_size);
} }
if (!src->data) { if (!src->data) {
src->data = read_sha1_file(src_entry->sha1, type, &sz); src->data = read_sha1_file(src_entry->sha1, &type, &sz);
if (sz != src_size) if (sz != src_size)
die("object %s inconsistent object length (%lu vs %lu)", die("object %s inconsistent object length (%lu vs %lu)",
sha1_to_hex(src_entry->sha1), sz, src_size); sha1_to_hex(src_entry->sha1), sz, src_size);
@ -1551,9 +1538,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
int use_internal_rev_list = 0; int use_internal_rev_list = 0;
int thin = 0; int thin = 0;
int i; int i;
const char *rp_av[64]; const char **rp_av;
int rp_ac_alloc = 64;
int rp_ac; int rp_ac;
rp_av = xcalloc(rp_ac_alloc, sizeof(*rp_av));
rp_av[0] = "pack-objects"; rp_av[0] = "pack-objects";
rp_av[1] = "--objects"; /* --thin will make it --objects-edge */ rp_av[1] = "--objects"; /* --thin will make it --objects-edge */
rp_ac = 2; rp_ac = 2;
@ -1579,14 +1569,14 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
incremental = 1; incremental = 1;
continue; continue;
} }
if (!strncmp("--window=", arg, 9)) { if (!prefixcmp(arg, "--window=")) {
char *end; char *end;
window = strtoul(arg+9, &end, 0); window = strtoul(arg+9, &end, 0);
if (!arg[9] || *end) if (!arg[9] || *end)
usage(pack_usage); usage(pack_usage);
continue; continue;
} }
if (!strncmp("--depth=", arg, 8)) { if (!prefixcmp(arg, "--depth=")) {
char *end; char *end;
depth = strtoul(arg+8, &end, 0); depth = strtoul(arg+8, &end, 0);
if (!arg[8] || *end) if (!arg[8] || *end)
@ -1622,12 +1612,15 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
continue; continue;
} }
if (!strcmp("--unpacked", arg) || if (!strcmp("--unpacked", arg) ||
!strncmp("--unpacked=", arg, 11) || !prefixcmp(arg, "--unpacked=") ||
!strcmp("--reflog", arg) || !strcmp("--reflog", arg) ||
!strcmp("--all", arg)) { !strcmp("--all", arg)) {
use_internal_rev_list = 1; use_internal_rev_list = 1;
if (ARRAY_SIZE(rp_av) - 1 <= rp_ac) if (rp_ac >= rp_ac_alloc - 1) {
die("too many internal rev-list options"); rp_ac_alloc = alloc_nr(rp_ac_alloc);
rp_av = xrealloc(rp_av,
rp_ac_alloc * sizeof(*rp_av));
}
rp_av[rp_ac++] = arg; rp_av[rp_ac++] = arg;
continue; continue;
} }

Просмотреть файл

@ -36,7 +36,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
/* Do not pack the symbolic refs */ /* Do not pack the symbolic refs */
if ((flags & REF_ISSYMREF)) if ((flags & REF_ISSYMREF))
return 0; return 0;
is_tag_ref = !strncmp(path, "refs/tags/", 10); is_tag_ref = !prefixcmp(path, "refs/tags/");
/* ALWAYS pack refs that were already packed or are tags */ /* ALWAYS pack refs that were already packed or are tags */
if (!cb->all && !is_tag_ref && !(flags & REF_ISPACKED)) if (!cb->all && !is_tag_ref && !(flags & REF_ISPACKED))

Просмотреть файл

@ -10,15 +10,10 @@ static int show_only;
static int prune_object(char *path, const char *filename, const unsigned char *sha1) static int prune_object(char *path, const char *filename, const unsigned char *sha1)
{ {
char buf[20];
const char *type;
if (show_only) { if (show_only) {
if (sha1_object_info(sha1, buf, NULL)) enum object_type type = sha1_object_info(sha1, NULL);
type = "unknown"; printf("%s %s\n", sha1_to_hex(sha1),
else (type > 0) ? typename(type) : "unknown");
type = buf;
printf("%s %s\n", sha1_to_hex(sha1), type);
return 0; return 0;
} }
unlink(mkpath("%s/%s", path, filename)); unlink(mkpath("%s/%s", path, filename));

Просмотреть файл

@ -32,7 +32,7 @@ static int expand_one_ref(const char *ref, const unsigned char *sha1, int flag,
/* Ignore the "refs/" at the beginning of the refname */ /* Ignore the "refs/" at the beginning of the refname */
ref += 5; ref += 5;
if (!strncmp(ref, "tags/", 5)) if (!prefixcmp(ref, "tags/"))
add_refspec(xstrdup(ref)); add_refspec(xstrdup(ref));
return 0; return 0;
} }
@ -149,10 +149,10 @@ static int get_remotes_uri(const char *repo, const char *uri[MAX_URI])
int is_refspec; int is_refspec;
char *s, *p; char *s, *p;
if (!strncmp("URL:", buffer, 4)) { if (!prefixcmp(buffer, "URL:")) {
is_refspec = 0; is_refspec = 0;
s = buffer + 4; s = buffer + 4;
} else if (!strncmp("Push:", buffer, 5)) { } else if (!prefixcmp(buffer, "Push:")) {
is_refspec = 1; is_refspec = 1;
s = buffer + 5; s = buffer + 5;
} else } else
@ -195,7 +195,7 @@ static int config_get_receivepack;
static int get_remote_config(const char* key, const char* value) static int get_remote_config(const char* key, const char* value)
{ {
if (!strncmp(key, "remote.", 7) && if (!prefixcmp(key, "remote.") &&
!strncmp(key + 7, config_repo, config_repo_len)) { !strncmp(key + 7, config_repo, config_repo_len)) {
if (!strcmp(key + 7 + config_repo_len, ".url")) { if (!strcmp(key + 7 + config_repo_len, ".url")) {
if (config_current_uri < MAX_URI) if (config_current_uri < MAX_URI)
@ -324,8 +324,8 @@ static int do_push(const char *repo)
const char **dest_refspec = refspec; const char **dest_refspec = refspec;
const char *dest = uri[i]; const char *dest = uri[i];
const char *sender = "git-send-pack"; const char *sender = "git-send-pack";
if (!strncmp(dest, "http://", 7) || if (!prefixcmp(dest, "http://") ||
!strncmp(dest, "https://", 8)) !prefixcmp(dest, "https://"))
sender = "git-http-push"; sender = "git-http-push";
else if (thin) else if (thin)
argv[dest_argc++] = "--thin"; argv[dest_argc++] = "--thin";
@ -373,7 +373,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
verbose=1; verbose=1;
continue; continue;
} }
if (!strncmp(arg, "--repo=", 7)) { if (!prefixcmp(arg, "--repo=")) {
repo = arg+7; repo = arg+7;
continue; continue;
} }
@ -397,11 +397,11 @@ int cmd_push(int argc, const char **argv, const char *prefix)
thin = 0; thin = 0;
continue; continue;
} }
if (!strncmp(arg, "--receive-pack=", 15)) { if (!prefixcmp(arg, "--receive-pack=")) {
receivepack = arg; receivepack = arg;
continue; continue;
} }
if (!strncmp(arg, "--exec=", 7)) { if (!prefixcmp(arg, "--exec=")) {
receivepack = arg; receivepack = arg;
continue; continue;
} }

Просмотреть файл

@ -133,7 +133,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
* entries and put the entries from the tree under the * entries and put the entries from the tree under the
* given subdirectory. * given subdirectory.
*/ */
if (!strncmp(arg, "--prefix=", 9)) { if (!prefixcmp(arg, "--prefix=")) {
if (stage || opts.merge || opts.prefix) if (stage || opts.merge || opts.prefix)
usage(read_tree_usage); usage(read_tree_usage);
opts.prefix = arg + 9; opts.prefix = arg + 9;
@ -179,7 +179,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
continue; continue;
} }
if (!strncmp(arg, "--exclude-per-directory=", 24)) { if (!prefixcmp(arg, "--exclude-per-directory=")) {
struct dir_struct *dir; struct dir_struct *dir;
if (opts.dir) if (opts.dir)

Просмотреть файл

@ -55,8 +55,8 @@ static int tree_is_complete(const unsigned char *sha1)
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
if (!desc.buf) { if (!desc.buf) {
char type[20]; enum object_type type;
void *data = read_sha1_file(sha1, type, &desc.size); void *data = read_sha1_file(sha1, &type, &desc.size);
if (!data) { if (!data) {
tree->object.flags |= INCOMPLETE; tree->object.flags |= INCOMPLETE;
return 0; return 0;
@ -215,8 +215,8 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
old = lookup_commit_reference_gently(osha1, 1); old = lookup_commit_reference_gently(osha1, 1);
if (!new && !is_null_sha1(nsha1)) if (!new && !is_null_sha1(nsha1))
new = lookup_commit_reference_gently(nsha1, 1); new = lookup_commit_reference_gently(nsha1, 1);
if ((old && !in_merge_bases(old, cb->ref_commit)) || if ((old && !in_merge_bases(old, &cb->ref_commit, 1)) ||
(new && !in_merge_bases(new, cb->ref_commit))) (new && !in_merge_bases(new, &cb->ref_commit, 1)))
goto prune; goto prune;
} }
@ -321,9 +321,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
const char *arg = argv[i]; const char *arg = argv[i];
if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
cb.dry_run = 1; cb.dry_run = 1;
else if (!strncmp(arg, "--expire=", 9)) else if (!prefixcmp(arg, "--expire="))
cb.expire_total = approxidate(arg + 9); cb.expire_total = approxidate(arg + 9);
else if (!strncmp(arg, "--expire-unreachable=", 21)) else if (!prefixcmp(arg, "--expire-unreachable="))
cb.expire_unreachable = approxidate(arg + 21); cb.expire_unreachable = approxidate(arg + 21);
else if (!strcmp(arg, "--stale-fix")) else if (!strcmp(arg, "--stale-fix"))
cb.stalefix = 1; cb.stalefix = 1;

Просмотреть файл

@ -105,11 +105,11 @@ static int handle_file(const char *path,
SHA1_Init(&ctx); SHA1_Init(&ctx);
while (fgets(buf, sizeof(buf), f)) { while (fgets(buf, sizeof(buf), f)) {
if (!strncmp("<<<<<<< ", buf, 8)) if (!prefixcmp(buf, "<<<<<<< "))
hunk = 1; hunk = 1;
else if (!strncmp("=======", buf, 7)) else if (!prefixcmp(buf, "======="))
hunk = 2; hunk = 2;
else if (!strncmp(">>>>>>> ", buf, 8)) { else if (!prefixcmp(buf, ">>>>>>> ")) {
hunk_no++; hunk_no++;
hunk = 0; hunk = 0;
if (memcmp(one->ptr, two->ptr, one->nr < two->nr ? if (memcmp(one->ptr, two->ptr, one->nr < two->nr ?
@ -154,13 +154,17 @@ static int find_conflict(struct path_list *conflict)
return error("Could not read index"); return error("Could not read index");
for (i = 0; i + 2 < active_nr; i++) { for (i = 0; i + 2 < active_nr; i++) {
struct cache_entry *e1 = active_cache[i]; struct cache_entry *e1 = active_cache[i];
struct cache_entry *e2 = active_cache[i + 1]; struct cache_entry *e2 = active_cache[i+1];
struct cache_entry *e3 = active_cache[i + 2]; struct cache_entry *e3 = active_cache[i+2];
if (ce_stage(e1) == 1 && ce_stage(e2) == 2 && if (ce_stage(e1) == 1 &&
ce_stage(e3) == 3 && ce_same_name(e1, e2) && ce_stage(e2) == 2 &&
ce_same_name(e1, e3)) { ce_stage(e3) == 3 &&
ce_same_name(e1, e2) && ce_same_name(e1, e3) &&
S_ISREG(ntohl(e1->ce_mode)) &&
S_ISREG(ntohl(e2->ce_mode)) &&
S_ISREG(ntohl(e3->ce_mode))) {
path_list_insert((const char *)e1->name, conflict); path_list_insert((const char *)e1->name, conflict);
i += 3; i += 2;
} }
} }
return 0; return 0;

Просмотреть файл

@ -226,6 +226,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
int i; int i;
int read_from_stdin = 0; int read_from_stdin = 0;
git_config(git_default_config);
init_revisions(&revs, prefix); init_revisions(&revs, prefix);
revs.abbrev = 0; revs.abbrev = 0;
revs.commit_format = CMIT_FMT_UNSPECIFIED; revs.commit_format = CMIT_FMT_UNSPECIFIED;

Просмотреть файл

@ -233,7 +233,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
} }
continue; continue;
} }
if (!strncmp(arg,"-n",2)) { if (!prefixcmp(arg, "-n")) {
if ((filter & DO_FLAGS) && (filter & DO_REVS)) if ((filter & DO_FLAGS) && (filter & DO_REVS))
show(arg); show(arg);
continue; continue;
@ -274,7 +274,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue; continue;
} }
if (!strcmp(arg, "--short") || if (!strcmp(arg, "--short") ||
!strncmp(arg, "--short=", 8)) { !prefixcmp(arg, "--short=")) {
filter &= ~(DO_FLAGS|DO_NOREV); filter &= ~(DO_FLAGS|DO_NOREV);
verify = 1; verify = 1;
abbrev = DEFAULT_ABBREV; abbrev = DEFAULT_ABBREV;
@ -352,19 +352,19 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
: "false"); : "false");
continue; continue;
} }
if (!strncmp(arg, "--since=", 8)) { if (!prefixcmp(arg, "--since=")) {
show_datestring("--max-age=", arg+8); show_datestring("--max-age=", arg+8);
continue; continue;
} }
if (!strncmp(arg, "--after=", 8)) { if (!prefixcmp(arg, "--after=")) {
show_datestring("--max-age=", arg+8); show_datestring("--max-age=", arg+8);
continue; continue;
} }
if (!strncmp(arg, "--before=", 9)) { if (!prefixcmp(arg, "--before=")) {
show_datestring("--min-age=", arg+9); show_datestring("--min-age=", arg+9);
continue; continue;
} }
if (!strncmp(arg, "--until=", 8)) { if (!prefixcmp(arg, "--until=")) {
show_datestring("--min-age=", arg+8); show_datestring("--min-age=", arg+8);
continue; continue;
} }

Просмотреть файл

@ -124,7 +124,7 @@ static void insert_author_oneline(struct path_list *list,
else else
free(buffer); free(buffer);
if (!strncmp(oneline, "[PATCH", 6)) { if (!prefixcmp(oneline, "[PATCH")) {
char *eob = strchr(oneline, ']'); char *eob = strchr(oneline, ']');
if (eob) { if (eob) {
@ -179,7 +179,7 @@ static void read_from_stdin(struct path_list *list)
while (fgets(buffer, sizeof(buffer), stdin) != NULL) { while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
char *bob; char *bob;
if ((buffer[0] == 'A' || buffer[0] == 'a') && if ((buffer[0] == 'A' || buffer[0] == 'a') &&
!strncmp(buffer + 1, "uthor: ", 7) && !prefixcmp(buffer + 1, "uthor: ") &&
(bob = strchr(buffer + 7, '<')) != NULL) { (bob = strchr(buffer + 7, '<')) != NULL) {
char buffer2[1024], offset = 0; char buffer2[1024], offset = 0;
@ -230,7 +230,7 @@ static void get_from_rev(struct rev_info *rev, struct path_list *list)
else else
eol++; eol++;
if (!strncmp(buffer, "author ", 7)) { if (!prefixcmp(buffer, "author ")) {
char *bracket = strchr(buffer, '<'); char *bracket = strchr(buffer, '<');
if (bracket == NULL || bracket > eol) if (bracket == NULL || bracket > eol)

Просмотреть файл

@ -266,7 +266,7 @@ static void show_one_commit(struct commit *commit, int no_name)
pretty, sizeof(pretty), 0, NULL, NULL, 0); pretty, sizeof(pretty), 0, NULL, NULL, 0);
else else
strcpy(pretty, "(unavailable)"); strcpy(pretty, "(unavailable)");
if (!strncmp(pretty, "[PATCH] ", 8)) if (!prefixcmp(pretty, "[PATCH] "))
cp = pretty + 8; cp = pretty + 8;
else else
cp = pretty; cp = pretty;
@ -378,7 +378,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1, int f
{ {
unsigned char tmp[20]; unsigned char tmp[20];
int ofs = 11; int ofs = 11;
if (strncmp(refname, "refs/heads/", ofs)) if (prefixcmp(refname, "refs/heads/"))
return 0; return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would /* If both heads/foo and tags/foo exists, get_sha1 would
* get confused. * get confused.
@ -392,7 +392,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
{ {
unsigned char tmp[20]; unsigned char tmp[20];
int ofs = 13; int ofs = 13;
if (strncmp(refname, "refs/remotes/", ofs)) if (prefixcmp(refname, "refs/remotes/"))
return 0; return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would /* If both heads/foo and tags/foo exists, get_sha1 would
* get confused. * get confused.
@ -404,7 +404,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{ {
if (strncmp(refname, "refs/tags/", 10)) if (prefixcmp(refname, "refs/tags/"))
return 0; return 0;
return append_ref(refname + 5, sha1, 0); return append_ref(refname + 5, sha1, 0);
} }
@ -435,9 +435,9 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i
return 0; return 0;
if (fnmatch(match_ref_pattern, tail, 0)) if (fnmatch(match_ref_pattern, tail, 0))
return 0; return 0;
if (!strncmp("refs/heads/", refname, 11)) if (!prefixcmp(refname, "refs/heads/"))
return append_head_ref(refname, sha1, flag, cb_data); return append_head_ref(refname, sha1, flag, cb_data);
if (!strncmp("refs/tags/", refname, 10)) if (!prefixcmp(refname, "refs/tags/"))
return append_tag_ref(refname, sha1, flag, cb_data); return append_tag_ref(refname, sha1, flag, cb_data);
return append_ref(refname, sha1, 0); return append_ref(refname, sha1, 0);
} }
@ -462,11 +462,11 @@ static int rev_is_head(char *head, int headlen, char *name,
if ((!head[0]) || if ((!head[0]) ||
(head_sha1 && sha1 && hashcmp(head_sha1, sha1))) (head_sha1 && sha1 && hashcmp(head_sha1, sha1)))
return 0; return 0;
if (!strncmp(head, "refs/heads/", 11)) if (!prefixcmp(head, "refs/heads/"))
head += 11; head += 11;
if (!strncmp(name, "refs/heads/", 11)) if (!prefixcmp(name, "refs/heads/"))
name += 11; name += 11;
else if (!strncmp(name, "heads/", 6)) else if (!prefixcmp(name, "heads/"))
name += 6; name += 6;
return !strcmp(head, name); return !strcmp(head, name);
} }
@ -635,7 +635,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
with_current_branch = 1; with_current_branch = 1;
else if (!strcmp(arg, "--sha1-name")) else if (!strcmp(arg, "--sha1-name"))
sha1_name = 1; sha1_name = 1;
else if (!strncmp(arg, "--more=", 7)) else if (!prefixcmp(arg, "--more="))
extra = atoi(arg + 7); extra = atoi(arg + 7);
else if (!strcmp(arg, "--merge-base")) else if (!strcmp(arg, "--merge-base"))
merge_base = 1; merge_base = 1;
@ -652,9 +652,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) { else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
reflog = DEFAULT_REFLOG; reflog = DEFAULT_REFLOG;
} }
else if (!strncmp(arg, "--reflog=", 9)) else if (!prefixcmp(arg, "--reflog="))
parse_reflog_param(arg + 9, &reflog, &reflog_base); parse_reflog_param(arg + 9, &reflog, &reflog_base);
else if (!strncmp(arg, "-g=", 3)) else if (!prefixcmp(arg, "-g="))
parse_reflog_param(arg + 3, &reflog, &reflog_base); parse_reflog_param(arg + 3, &reflog, &reflog_base);
else else
usage(show_branch_usage); usage(show_branch_usage);

Просмотреть файл

@ -28,8 +28,8 @@ static int show_ref(const char *refname, const unsigned char *sha1, int flag, vo
if (tags_only || heads_only) { if (tags_only || heads_only) {
int match; int match;
match = heads_only && !strncmp(refname, "refs/heads/", 11); match = heads_only && !prefixcmp(refname, "refs/heads/");
match |= tags_only && !strncmp(refname, "refs/tags/", 10); match |= tags_only && !prefixcmp(refname, "refs/tags/");
if (!match) if (!match)
return 0; return 0;
} }
@ -178,8 +178,8 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
hash_only = 1; hash_only = 1;
continue; continue;
} }
if (!strncmp(arg, "--hash=", 7) || if (!prefixcmp(arg, "--hash=") ||
(!strncmp(arg, "--abbrev", 8) && (!prefixcmp(arg, "--abbrev") &&
(arg[8] == '=' || arg[8] == '\0'))) { (arg[8] == '=' || arg[8] == '\0'))) {
if (arg[2] != 'h' && !arg[8]) if (arg[2] != 'h' && !arg[8])
/* --abbrev only */ /* --abbrev only */
@ -215,16 +215,18 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
} }
if (!strcmp(arg, "--exclude-existing")) if (!strcmp(arg, "--exclude-existing"))
return exclude_existing(NULL); return exclude_existing(NULL);
if (!strncmp(arg, "--exclude-existing=", 19)) if (!prefixcmp(arg, "--exclude-existing="))
return exclude_existing(arg + 19); return exclude_existing(arg + 19);
usage(show_ref_usage); usage(show_ref_usage);
} }
if (verify) { if (verify) {
unsigned char sha1[20]; if (!pattern)
die("--verify requires a reference");
while (*pattern) { while (*pattern) {
if (!strncmp(*pattern, "refs/", 5) && unsigned char sha1[20];
if (!prefixcmp(*pattern, "refs/") &&
resolve_ref(*pattern, sha1, 1, NULL)) { resolve_ref(*pattern, sha1, 1, NULL)) {
if (!quiet) if (!quiet)
show_one(*pattern, sha1); show_one(*pattern, sha1);

Просмотреть файл

@ -31,7 +31,7 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)
nargv[nargc++] = "git-archive"; nargv[nargc++] = "git-archive";
nargv[nargc++] = "--format=tar"; nargv[nargc++] = "--format=tar";
if (2 <= argc && !strncmp("--remote=", argv[1], 9)) { if (2 <= argc && !prefixcmp(argv[1], "--remote=")) {
nargv[nargc++] = argv[1]; nargv[nargc++] = argv[1];
argv++; argv++;
argc--; argc--;

Просмотреть файл

@ -119,18 +119,18 @@ struct obj_info {
static struct obj_info *obj_list; static struct obj_info *obj_list;
static void added_object(unsigned nr, const char *type, void *data, static void added_object(unsigned nr, enum object_type type,
unsigned long size); void *data, unsigned long size);
static void write_object(unsigned nr, void *buf, unsigned long size, static void write_object(unsigned nr, enum object_type type,
const char *type) void *buf, unsigned long size)
{ {
if (write_sha1_file(buf, size, type, obj_list[nr].sha1) < 0) if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
die("failed to write object"); die("failed to write object");
added_object(nr, type, buf, size); added_object(nr, type, buf, size);
} }
static void resolve_delta(unsigned nr, const char *type, static void resolve_delta(unsigned nr, enum object_type type,
void *base, unsigned long base_size, void *base, unsigned long base_size,
void *delta, unsigned long delta_size) void *delta, unsigned long delta_size)
{ {
@ -143,12 +143,12 @@ static void resolve_delta(unsigned nr, const char *type,
if (!result) if (!result)
die("failed to apply delta"); die("failed to apply delta");
free(delta); free(delta);
write_object(nr, result, result_size, type); write_object(nr, type, result, result_size);
free(result); free(result);
} }
static void added_object(unsigned nr, const char *type, void *data, static void added_object(unsigned nr, enum object_type type,
unsigned long size) void *data, unsigned long size)
{ {
struct delta_info **p = &delta_list; struct delta_info **p = &delta_list;
struct delta_info *info; struct delta_info *info;
@ -167,33 +167,24 @@ static void added_object(unsigned nr, const char *type, void *data,
} }
} }
static void unpack_non_delta_entry(enum object_type kind, unsigned long size, static void unpack_non_delta_entry(enum object_type type, unsigned long size,
unsigned nr) unsigned nr)
{ {
void *buf = get_data(size); void *buf = get_data(size);
const char *type;
switch (kind) {
case OBJ_COMMIT: type = commit_type; break;
case OBJ_TREE: type = tree_type; break;
case OBJ_BLOB: type = blob_type; break;
case OBJ_TAG: type = tag_type; break;
default: die("bad type %d", kind);
}
if (!dry_run && buf) if (!dry_run && buf)
write_object(nr, buf, size, type); write_object(nr, type, buf, size);
free(buf); free(buf);
} }
static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
unsigned nr) unsigned nr)
{ {
void *delta_data, *base; void *delta_data, *base;
unsigned long base_size; unsigned long base_size;
char type[20];
unsigned char base_sha1[20]; unsigned char base_sha1[20];
if (kind == OBJ_REF_DELTA) { if (type == OBJ_REF_DELTA) {
hashcpy(base_sha1, fill(20)); hashcpy(base_sha1, fill(20));
use(20); use(20);
delta_data = get_data(delta_size); delta_data = get_data(delta_size);
@ -255,7 +246,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size,
} }
} }
base = read_sha1_file(base_sha1, type, &base_size); base = read_sha1_file(base_sha1, &type, &base_size);
if (!base) { if (!base) {
error("failed to read delta-pack base object %s", error("failed to read delta-pack base object %s",
sha1_to_hex(base_sha1)); sha1_to_hex(base_sha1));
@ -369,7 +360,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
recover = 1; recover = 1;
continue; continue;
} }
if (!strncmp(arg, "--pack_header=", 14)) { if (!prefixcmp(arg, "--pack_header=")) {
struct pack_header *hdr; struct pack_header *hdr;
char *c; char *c;

Просмотреть файл

@ -109,16 +109,17 @@ static int add_file_to_cache(const char *path)
ce->ce_flags = htons(namelen); ce->ce_flags = htons(namelen);
fill_stat_cache_info(ce, &st); fill_stat_cache_info(ce, &st);
ce->ce_mode = create_ce_mode(st.st_mode); if (trust_executable_bit)
if (!trust_executable_bit) { ce->ce_mode = create_ce_mode(st.st_mode);
else {
/* If there is an existing entry, pick the mode bits /* If there is an existing entry, pick the mode bits
* from it, otherwise assume unexecutable. * from it, otherwise assume unexecutable.
*/ */
struct cache_entry *ent;
int pos = cache_name_pos(path, namelen); int pos = cache_name_pos(path, namelen);
if (0 <= pos)
ce->ce_mode = active_cache[pos]->ce_mode; ent = (0 <= pos) ? active_cache[pos] : NULL;
else if (S_ISREG(st.st_mode)) ce->ce_mode = ce_mode_from_stat(ent, st.st_mode);
ce->ce_mode = create_ce_mode(S_IFREG | 0666);
} }
if (index_path(ce->sha1, path, &st, !info_only)) if (index_path(ce->sha1, path, &st, !info_only))

Просмотреть файл

@ -70,7 +70,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
const char *arg = argv[1]; const char *arg = argv[1];
if (!strcmp(arg, "--missing-ok")) if (!strcmp(arg, "--missing-ok"))
missing_ok = 1; missing_ok = 1;
else if (!strncmp(arg, "--prefix=", 9)) else if (!prefixcmp(arg, "--prefix="))
prefix = arg + 9; prefix = arg + 9;
else else
usage(write_tree_usage); usage(write_tree_usage);

Просмотреть файл

@ -29,7 +29,6 @@ extern int cmd_describe(int argc, const char **argv, const char *prefix);
extern int cmd_diff_files(int argc, const char **argv, const char *prefix); extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
extern int cmd_diff_index(int argc, const char **argv, const char *prefix); extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
extern int cmd_diff(int argc, const char **argv, const char *prefix); extern int cmd_diff(int argc, const char **argv, const char *prefix);
extern int cmd_diff_stages(int argc, const char **argv, const char *prefix);
extern int cmd_diff_tree(int argc, const char **argv, const char *prefix); extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix); extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix);
extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix); extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
@ -46,6 +45,7 @@ extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
extern int cmd_ls_tree(int argc, const char **argv, const char *prefix); extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
extern int cmd_mailinfo(int argc, const char **argv, const char *prefix); extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
extern int cmd_mailsplit(int argc, const char **argv, const char *prefix); extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
extern int cmd_merge_file(int argc, const char **argv, const char *prefix); extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix); extern int cmd_mv(int argc, const char **argv, const char *prefix);
extern int cmd_name_rev(int argc, const char **argv, const char *prefix); extern int cmd_name_rev(int argc, const char **argv, const char *prefix);

51
cache.h
Просмотреть файл

@ -106,6 +106,16 @@ static inline unsigned int create_ce_mode(unsigned int mode)
return htonl(S_IFLNK); return htonl(S_IFLNK);
return htonl(S_IFREG | ce_permissions(mode)); return htonl(S_IFREG | ce_permissions(mode));
} }
static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
{
extern int trust_executable_bit;
if (!trust_executable_bit && S_ISREG(mode)) {
if (ce && S_ISREG(ntohl(ce->ce_mode)))
return ce->ce_mode;
return create_ce_mode(0666);
}
return create_ce_mode(mode);
}
#define canon_mode(mode) \ #define canon_mode(mode) \
(S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
S_ISLNK(mode) ? S_IFLNK : S_IFDIR) S_ISLNK(mode) ? S_IFLNK : S_IFDIR)
@ -201,6 +211,7 @@ extern const char *apply_default_whitespace;
extern int zlib_compression_level; extern int zlib_compression_level;
extern size_t packed_git_window_size; extern size_t packed_git_window_size;
extern size_t packed_git_limit; extern size_t packed_git_limit;
extern int auto_crlf;
#define GIT_REPO_VERSION 0 #define GIT_REPO_VERSION 0
extern int repository_format_version; extern int repository_format_version;
@ -251,13 +262,25 @@ int adjust_shared_perm(const char *path);
int safe_create_leading_directories(char *path); int safe_create_leading_directories(char *path);
char *enter_repo(char *path, int strict); char *enter_repo(char *path, int strict);
enum object_type {
OBJ_NONE = 0,
OBJ_COMMIT = 1,
OBJ_TREE = 2,
OBJ_BLOB = 3,
OBJ_TAG = 4,
/* 5 for future expansion */
OBJ_OFS_DELTA = 6,
OBJ_REF_DELTA = 7,
OBJ_BAD,
};
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */ /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
extern int sha1_object_info(const unsigned char *, char *, unsigned long *); extern int sha1_object_info(const unsigned char *, unsigned long *);
extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size); extern void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size);
extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size); extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size);
extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1); extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1);
extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1); extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
extern int pretend_sha1_file(void *, unsigned long, const char *, unsigned char *); extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type); extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
@ -274,18 +297,6 @@ extern int legacy_loose_object(unsigned char *);
extern int has_pack_file(const unsigned char *sha1); extern int has_pack_file(const unsigned char *sha1);
extern int has_pack_index(const unsigned char *sha1); extern int has_pack_index(const unsigned char *sha1);
enum object_type {
OBJ_NONE = 0,
OBJ_COMMIT = 1,
OBJ_TREE = 2,
OBJ_BLOB = 3,
OBJ_TAG = 4,
/* 5 for future expansion */
OBJ_OFS_DELTA = 6,
OBJ_REF_DELTA = 7,
OBJ_BAD,
};
extern signed char hexval_table[256]; extern signed char hexval_table[256];
static inline unsigned int hexval(unsigned int c) static inline unsigned int hexval(unsigned int c)
{ {
@ -411,9 +422,9 @@ extern struct packed_git *add_packed_git(char *, int, int);
extern int num_packed_objects(const struct packed_git *p); extern int num_packed_objects(const struct packed_git *p);
extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*); extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*);
extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *); extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *);
extern void *unpack_entry(struct packed_git *, unsigned long, char *, unsigned long *); extern void *unpack_entry(struct packed_git *, unsigned long, enum object_type *, unsigned long *);
extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep); extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
extern void packed_object_info_detail(struct packed_git *, unsigned long, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *); extern const char *packed_object_info_detail(struct packed_git *, unsigned long, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
/* Dumb servers support */ /* Dumb servers support */
extern int update_server_info(int); extern int update_server_info(int);
@ -468,4 +479,8 @@ extern int nfvasprintf(char **str, const char *fmt, va_list va);
extern void trace_printf(const char *format, ...); extern void trace_printf(const char *format, ...);
extern void trace_argv_printf(const char **argv, int count, const char *format, ...); extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
/* convert.c */
extern int convert_to_git(const char *path, char **bufp, unsigned long *sizep);
extern int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep);
#endif /* CACHE_H */ #endif /* CACHE_H */

Просмотреть файл

@ -92,14 +92,14 @@ struct sline {
static char *grab_blob(const unsigned char *sha1, unsigned long *size) static char *grab_blob(const unsigned char *sha1, unsigned long *size)
{ {
char *blob; char *blob;
char type[20]; enum object_type type;
if (is_null_sha1(sha1)) { if (is_null_sha1(sha1)) {
/* deleted blob */ /* deleted blob */
*size = 0; *size = 0;
return xcalloc(1, 1); return xcalloc(1, 1);
} }
blob = read_sha1_file(sha1, type, size); blob = read_sha1_file(sha1, &type, size);
if (strcmp(type, blob_type)) if (type != OBJ_BLOB)
die("object '%s' is not a blob!", sha1_to_hex(sha1)); die("object '%s' is not a blob!", sha1_to_hex(sha1));
return blob; return blob;
} }
@ -678,11 +678,27 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
else { else {
/* Used by diff-tree to read from the working tree */ /* Used by diff-tree to read from the working tree */
struct stat st; struct stat st;
int fd; int fd = -1;
if (0 <= (fd = open(elem->path, O_RDONLY)) &&
!fstat(fd, &st)) { if (lstat(elem->path, &st) < 0)
int len = st.st_size; goto deleted_file;
int sz = 0;
if (S_ISLNK(st.st_mode)) {
size_t len = st.st_size;
result_size = len;
result = xmalloc(len + 1);
if (result_size != readlink(elem->path, result, len)) {
error("readlink(%s): %s", elem->path,
strerror(errno));
return;
}
result[len] = 0;
elem->mode = canon_mode(st.st_mode);
}
else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
!fstat(fd, &st)) {
size_t len = st.st_size;
size_t sz = 0;
elem->mode = canon_mode(st.st_mode); elem->mode = canon_mode(st.st_mode);
result_size = len; result_size = len;
@ -698,11 +714,12 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
result[len] = 0; result[len] = 0;
} }
else { else {
/* deleted file */ deleted_file:
result_size = 0; result_size = 0;
elem->mode = 0; elem->mode = 0;
result = xcalloc(1, 1); result = xcalloc(1, 1);
} }
if (0 <= fd) if (0 <= fd)
close(fd); close(fd);
} }

Просмотреть файл

@ -342,18 +342,18 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
int parse_commit(struct commit *item) int parse_commit(struct commit *item)
{ {
char type[20]; enum object_type type;
void *buffer; void *buffer;
unsigned long size; unsigned long size;
int ret; int ret;
if (item->object.parsed) if (item->object.parsed)
return 0; return 0;
buffer = read_sha1_file(item->object.sha1, type, &size); buffer = read_sha1_file(item->object.sha1, &type, &size);
if (!buffer) if (!buffer)
return error("Could not read %s", return error("Could not read %s",
sha1_to_hex(item->object.sha1)); sha1_to_hex(item->object.sha1));
if (strcmp(type, commit_type)) { if (type != OBJ_COMMIT) {
free(buffer); free(buffer);
return error("Object %s not a commit", return error("Object %s not a commit",
sha1_to_hex(item->object.sha1)); sha1_to_hex(item->object.sha1));
@ -1187,14 +1187,17 @@ struct commit_list *get_merge_bases(struct commit *one,
return result; return result;
} }
int in_merge_bases(struct commit *rev1, struct commit *rev2) int in_merge_bases(struct commit *commit, struct commit **reference, int num)
{ {
struct commit_list *bases, *b; struct commit_list *bases, *b;
int ret = 0; int ret = 0;
bases = get_merge_bases(rev1, rev2, 1); if (num == 1)
bases = get_merge_bases(commit, *reference, 1);
else
die("not yet");
for (b = bases; b; b = b->next) { for (b = bases; b; b = b->next) {
if (!hashcmp(rev1->object.sha1, b->item->object.sha1)) { if (!hashcmp(commit->object.sha1, b->item->object.sha1)) {
ret = 1; ret = 1;
break; break;
} }

Просмотреть файл

@ -114,5 +114,5 @@ extern int is_repository_shallow(void);
extern struct commit_list *get_shallow_commits(struct object_array *heads, extern struct commit_list *get_shallow_commits(struct object_array *heads,
int depth, int shallow_flag, int not_shallow_flag); int depth, int shallow_flag, int not_shallow_flag);
int in_merge_bases(struct commit *rev1, struct commit *rev2); int in_merge_bases(struct commit *, struct commit **, int);
#endif /* COMMIT_H */ #endif /* COMMIT_H */

10
compat/strtoumax.c Normal file
Просмотреть файл

@ -0,0 +1,10 @@
#include "../git-compat-util.h"
uintmax_t gitstrtoumax (const char *nptr, char **endptr, int base)
{
#if defined(NO_STRTOULL)
return strtoul(nptr, endptr, base);
#else
return strtoull(nptr, endptr, base);
#endif
}

Просмотреть файл

@ -310,12 +310,14 @@ int git_default_config(const char *var, const char *value)
} }
if (!strcmp(var, "core.packedgitwindowsize")) { if (!strcmp(var, "core.packedgitwindowsize")) {
int pgsz = getpagesize(); int pgsz_x2 = getpagesize() * 2;
packed_git_window_size = git_config_int(var, value); packed_git_window_size = git_config_int(var, value);
packed_git_window_size /= pgsz;
if (packed_git_window_size < 2) /* This value must be multiple of (pagesize * 2) */
packed_git_window_size = 2; packed_git_window_size /= pgsz_x2;
packed_git_window_size *= pgsz; if (packed_git_window_size < 1)
packed_git_window_size = 1;
packed_git_window_size *= pgsz_x2;
return 0; return 0;
} }
@ -324,6 +326,15 @@ int git_default_config(const char *var, const char *value)
return 0; return 0;
} }
if (!strcmp(var, "core.autocrlf")) {
if (value && !strcasecmp(value, "input")) {
auto_crlf = -1;
return 0;
}
auto_crlf = git_config_bool(var, value);
return 0;
}
if (!strcmp(var, "user.name")) { if (!strcmp(var, "user.name")) {
strlcpy(git_default_name, value, sizeof(git_default_name)); strlcpy(git_default_name, value, sizeof(git_default_name));
return 0; return 0;
@ -383,6 +394,8 @@ int git_config(config_fn_t fn)
* config file otherwise. */ * config file otherwise. */
filename = getenv(CONFIG_ENVIRONMENT); filename = getenv(CONFIG_ENVIRONMENT);
if (!filename) { if (!filename) {
if (!access(ETC_GITCONFIG, R_OK))
ret += git_config_from_file(fn, ETC_GITCONFIG);
home = getenv("HOME"); home = getenv("HOME");
filename = getenv(CONFIG_LOCAL_ENVIRONMENT); filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
if (!filename) if (!filename)

Просмотреть файл

@ -114,13 +114,32 @@ AC_CHECK_LIB([expat], [XML_ParserCreate],
[NO_EXPAT=YesPlease]) [NO_EXPAT=YesPlease])
AC_SUBST(NO_EXPAT) AC_SUBST(NO_EXPAT)
# #
# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin). # Define NEEDS_LIBICONV if linking with libc is not enough (Darwin and
# some Solaris installations).
# Define NO_ICONV if neither libc nor libiconv support iconv. # Define NO_ICONV if neither libc nor libiconv support iconv.
AC_CHECK_LIB([c], [iconv], AC_DEFUN([ICONVTEST_SRC], [
[NEEDS_LIBICONV=], #include <iconv.h>
AC_CHECK_LIB([iconv], [iconv],
[NEEDS_LIBICONV=YesPlease], int main(void)
[NO_ICONV=YesPlease])) {
iconv_open("", "");
return 0;
}
])
AC_MSG_CHECKING([for iconv in -lc])
AC_LINK_IFELSE(ICONVTEST_SRC,
[AC_MSG_RESULT([yes])
NEEDS_LIBICONV=],
[AC_MSG_RESULT([no])
old_LIBS="$LIBS"
LIBS="$LIBS -liconv"
AC_MSG_CHECKING([for iconv in -liconv])
AC_LINK_IFELSE(ICONVTEST_SRC,
[AC_MSG_RESULT([yes])
NEEDS_LIBICONV=YesPlease],
[AC_MSG_RESULT([no])
NO_ICONV=YesPlease])
LIBS="$old_LIBS"])
AC_SUBST(NEEDS_LIBICONV) AC_SUBST(NEEDS_LIBICONV)
AC_SUBST(NO_ICONV) AC_SUBST(NO_ICONV)
test -n "$NEEDS_LIBICONV" && LIBS="$LIBS -liconv" test -n "$NEEDS_LIBICONV" && LIBS="$LIBS -liconv"

Просмотреть файл

@ -96,7 +96,7 @@ int get_ack(int fd, unsigned char *result_sha1)
line[--len] = 0; line[--len] = 0;
if (!strcmp(line, "NAK")) if (!strcmp(line, "NAK"))
return 0; return 0;
if (!strncmp(line, "ACK ", 4)) { if (!prefixcmp(line, "ACK ")) {
if (!get_sha1_hex(line+4, result_sha1)) { if (!get_sha1_hex(line+4, result_sha1)) {
if (strstr(line+45, "continue")) if (strstr(line+45, "continue"))
return 2; return 2;
@ -196,8 +196,8 @@ static int count_refspec_match(const char *pattern,
*/ */
if (namelen != patlen && if (namelen != patlen &&
patlen != namelen - 5 && patlen != namelen - 5 &&
strncmp(name, "refs/heads/", 11) && prefixcmp(name, "refs/heads/") &&
strncmp(name, "refs/tags/", 10)) { prefixcmp(name, "refs/tags/")) {
/* We want to catch the case where only weak /* We want to catch the case where only weak
* matches are found and there are multiple * matches are found and there are multiple
* matches, and where more than one strong * matches, and where more than one strong

Просмотреть файл

@ -269,7 +269,6 @@ __git_commands ()
cvsimport) : import;; cvsimport) : import;;
cvsserver) : daemon;; cvsserver) : daemon;;
daemon) : daemon;; daemon) : daemon;;
diff-stages) : nobody uses it;;
fast-import) : import;; fast-import) : import;;
fsck-objects) : plumbing;; fsck-objects) : plumbing;;
fetch-pack) : plumbing;; fetch-pack) : plumbing;;
@ -298,7 +297,6 @@ __git_commands ()
reflog) : plumbing;; reflog) : plumbing;;
repo-config) : plumbing;; repo-config) : plumbing;;
rerere) : plumbing;; rerere) : plumbing;;
resolve) : dead dont use;;
rev-list) : plumbing;; rev-list) : plumbing;;
rev-parse) : plumbing;; rev-parse) : plumbing;;
runstatus) : plumbing;; runstatus) : plumbing;;

Просмотреть файл

Просмотреть файл

@ -25,11 +25,14 @@ foreach my $tar_file (@ARGV)
my $tar_name = $1; my $tar_name = $1;
if ($tar_name =~ s/\.(tar\.gz|tgz)$//) { if ($tar_name =~ s/\.(tar\.gz|tgz)$//) {
open(I, '-|', 'gzcat', $tar_file) or die "Unable to gzcat $tar_file: $!\n"; open(I, '-|', 'gunzip', '-c', $tar_file)
or die "Unable to gunzip -c $tar_file: $!\n";
} elsif ($tar_name =~ s/\.(tar\.bz2|tbz2)$//) { } elsif ($tar_name =~ s/\.(tar\.bz2|tbz2)$//) {
open(I, '-|', 'bzcat', $tar_file) or die "Unable to bzcat $tar_file: $!\n"; open(I, '-|', 'bunzip2', '-c', $tar_file)
or die "Unable to bunzip2 -c $tar_file: $!\n";
} elsif ($tar_name =~ s/\.tar\.Z$//) { } elsif ($tar_name =~ s/\.tar\.Z$//) {
open(I, '-|', 'zcat', $tar_file) or die "Unable to zcat $tar_file: $!\n"; open(I, '-|', 'uncompress', '-c', $tar_file)
or die "Unable to uncompress -c $tar_file: $!\n";
} elsif ($tar_name =~ s/\.tar$//) { } elsif ($tar_name =~ s/\.tar$//) {
open(I, $tar_file) or die "Unable to open $tar_file: $!\n"; open(I, $tar_file) or die "Unable to open $tar_file: $!\n";
} else { } else {

Просмотреть файл

@ -284,27 +284,27 @@ static void convert_commit(void *buffer, unsigned long size, unsigned char *resu
static struct entry * convert_entry(unsigned char *sha1) static struct entry * convert_entry(unsigned char *sha1)
{ {
struct entry *entry = lookup_entry(sha1); struct entry *entry = lookup_entry(sha1);
char type[20]; enum object_type type;
void *buffer, *data; void *buffer, *data;
unsigned long size; unsigned long size;
if (entry->converted) if (entry->converted)
return entry; return entry;
data = read_sha1_file(sha1, type, &size); data = read_sha1_file(sha1, &type, &size);
if (!data) if (!data)
die("unable to read object %s", sha1_to_hex(sha1)); die("unable to read object %s", sha1_to_hex(sha1));
buffer = xmalloc(size); buffer = xmalloc(size);
memcpy(buffer, data, size); memcpy(buffer, data, size);
if (!strcmp(type, blob_type)) { if (type == OBJ_BLOB) {
write_sha1_file(buffer, size, blob_type, entry->new_sha1); write_sha1_file(buffer, size, blob_type, entry->new_sha1);
} else if (!strcmp(type, tree_type)) } else if (type == OBJ_TREE)
convert_tree(buffer, size, entry->new_sha1); convert_tree(buffer, size, entry->new_sha1);
else if (!strcmp(type, commit_type)) else if (type == OBJ_COMMIT)
convert_commit(buffer, size, entry->new_sha1); convert_commit(buffer, size, entry->new_sha1);
else else
die("unknown object type '%s' in %s", type, sha1_to_hex(sha1)); die("unknown object type %d in %s", type, sha1_to_hex(sha1));
entry->converted = 1; entry->converted = 1;
free(buffer); free(buffer);
free(data); free(data);

186
convert.c Normal file
Просмотреть файл

@ -0,0 +1,186 @@
#include "cache.h"
/*
* convert.c - convert a file when checking it out and checking it in.
*
* This should use the pathname to decide on whether it wants to do some
* more interesting conversions (automatic gzip/unzip, general format
* conversions etc etc), but by default it just does automatic CRLF<->LF
* translation when the "auto_crlf" option is set.
*/
struct text_stat {
/* CR, LF and CRLF counts */
unsigned cr, lf, crlf;
/* These are just approximations! */
unsigned printable, nonprintable;
};
static void gather_stats(const char *buf, unsigned long size, struct text_stat *stats)
{
unsigned long i;
memset(stats, 0, sizeof(*stats));
for (i = 0; i < size; i++) {
unsigned char c = buf[i];
if (c == '\r') {
stats->cr++;
if (i+1 < size && buf[i+1] == '\n')
stats->crlf++;
continue;
}
if (c == '\n') {
stats->lf++;
continue;
}
if (c == 127)
/* DEL */
stats->nonprintable++;
else if (c < 32) {
switch (c) {
/* BS, HT, ESC and FF */
case '\b': case '\t': case '\033': case '\014':
stats->printable++;
break;
default:
stats->nonprintable++;
}
}
else
stats->printable++;
}
}
/*
* The same heuristics as diff.c::mmfile_is_binary()
*/
static int is_binary(unsigned long size, struct text_stat *stats)
{
if ((stats->printable >> 7) < stats->nonprintable)
return 1;
/*
* Other heuristics? Average line length might be relevant,
* as might LF vs CR vs CRLF counts..
*
* NOTE! It might be normal to have a low ratio of CRLF to LF
* (somebody starts with a LF-only file and edits it with an editor
* that adds CRLF only to lines that are added..). But do we
* want to support CR-only? Probably not.
*/
return 0;
}
int convert_to_git(const char *path, char **bufp, unsigned long *sizep)
{
char *buffer, *nbuf;
unsigned long size, nsize;
struct text_stat stats;
/*
* FIXME! Other pluggable conversions should go here,
* based on filename patterns. Right now we just do the
* stupid auto-CRLF one.
*/
if (!auto_crlf)
return 0;
size = *sizep;
if (!size)
return 0;
buffer = *bufp;
gather_stats(buffer, size, &stats);
/* No CR? Nothing to convert, regardless. */
if (!stats.cr)
return 0;
/*
* We're currently not going to even try to convert stuff
* that has bare CR characters. Does anybody do that crazy
* stuff?
*/
if (stats.cr != stats.crlf)
return 0;
/*
* And add some heuristics for binary vs text, of course...
*/
if (is_binary(size, &stats))
return 0;
/*
* Ok, allocate a new buffer, fill it in, and return true
* to let the caller know that we switched buffers on it.
*/
nsize = size - stats.crlf;
nbuf = xmalloc(nsize);
*bufp = nbuf;
*sizep = nsize;
do {
unsigned char c = *buffer++;
if (c != '\r')
*nbuf++ = c;
} while (--size);
return 1;
}
int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
{
char *buffer, *nbuf;
unsigned long size, nsize;
struct text_stat stats;
unsigned char last;
/*
* FIXME! Other pluggable conversions should go here,
* based on filename patterns. Right now we just do the
* stupid auto-CRLF one.
*/
if (auto_crlf <= 0)
return 0;
size = *sizep;
if (!size)
return 0;
buffer = *bufp;
gather_stats(buffer, size, &stats);
/* No LF? Nothing to convert, regardless. */
if (!stats.lf)
return 0;
/* Was it already in CRLF format? */
if (stats.lf == stats.crlf)
return 0;
/* If we have any bare CR characters, we're not going to touch it */
if (stats.cr != stats.crlf)
return 0;
if (is_binary(size, &stats))
return 0;
/*
* Ok, allocate a new buffer, fill it in, and return true
* to let the caller know that we switched buffers on it.
*/
nsize = size + stats.lf - stats.crlf;
nbuf = xmalloc(nsize);
*bufp = nbuf;
*sizep = nsize;
last = 0;
do {
unsigned char c = *buffer++;
if (c == '\n' && last != '\r')
*nbuf++ = '\r';
*nbuf++ = c;
last = c;
} while (--size);
return 1;
}

Просмотреть файл

@ -286,7 +286,7 @@ static int service_enabled;
static int git_daemon_config(const char *var, const char *value) static int git_daemon_config(const char *var, const char *value)
{ {
if (!strncmp(var, "daemon.", 7) && if (!prefixcmp(var, "daemon.") &&
!strcmp(var + 7, service_looking_at->config_name)) { !strcmp(var + 7, service_looking_at->config_name)) {
service_enabled = git_config_bool(var, value); service_enabled = git_config_bool(var, value);
return 0; return 0;
@ -562,7 +562,7 @@ static int execute(struct sockaddr *addr)
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) { for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]); struct daemon_service *s = &(daemon_service[i]);
int namelen = strlen(s->name); int namelen = strlen(s->name);
if (!strncmp("git-", line, 4) && if (!prefixcmp(line, "git-") &&
!strncmp(s->name, line + 4, namelen) && !strncmp(s->name, line + 4, namelen) &&
line[namelen + 4] == ' ') { line[namelen + 4] == ' ') {
/* /*
@ -773,6 +773,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
char pbuf[NI_MAXSERV]; char pbuf[NI_MAXSERV];
struct addrinfo hints, *ai0, *ai; struct addrinfo hints, *ai0, *ai;
int gai; int gai;
long flags;
sprintf(pbuf, "%d", listen_port); sprintf(pbuf, "%d", listen_port);
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
@ -820,6 +821,10 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
continue; /* not fatal */ continue; /* not fatal */
} }
flags = fcntl(sockfd, F_GETFD, 0);
if (flags >= 0)
fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
socklist = xrealloc(socklist, sizeof(int) * (socknum + 1)); socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
socklist[socknum++] = sockfd; socklist[socknum++] = sockfd;
@ -839,6 +844,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
{ {
struct sockaddr_in sin; struct sockaddr_in sin;
int sockfd; int sockfd;
long flags;
memset(&sin, 0, sizeof sin); memset(&sin, 0, sizeof sin);
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
@ -871,6 +877,10 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
return 0; return 0;
} }
flags = fcntl(sockfd, F_GETFD, 0);
if (flags >= 0)
fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
*socklist_p = xmalloc(sizeof(int)); *socklist_p = xmalloc(sizeof(int));
**socklist_p = sockfd; **socklist_p = sockfd;
return 1; return 1;
@ -1001,7 +1011,7 @@ int main(int argc, char **argv)
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
char *arg = argv[i]; char *arg = argv[i];
if (!strncmp(arg, "--listen=", 9)) { if (!prefixcmp(arg, "--listen=")) {
char *p = arg + 9; char *p = arg + 9;
char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1); char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1);
while (*p) while (*p)
@ -1009,7 +1019,7 @@ int main(int argc, char **argv)
*ph = 0; *ph = 0;
continue; continue;
} }
if (!strncmp(arg, "--port=", 7)) { if (!prefixcmp(arg, "--port=")) {
char *end; char *end;
unsigned long n; unsigned long n;
n = strtoul(arg+7, &end, 0); n = strtoul(arg+7, &end, 0);
@ -1035,11 +1045,11 @@ int main(int argc, char **argv)
export_all_trees = 1; export_all_trees = 1;
continue; continue;
} }
if (!strncmp(arg, "--timeout=", 10)) { if (!prefixcmp(arg, "--timeout=")) {
timeout = atoi(arg+10); timeout = atoi(arg+10);
continue; continue;
} }
if (!strncmp(arg, "--init-timeout=", 15)) { if (!prefixcmp(arg, "--init-timeout=")) {
init_timeout = atoi(arg+15); init_timeout = atoi(arg+15);
continue; continue;
} }
@ -1047,11 +1057,11 @@ int main(int argc, char **argv)
strict_paths = 1; strict_paths = 1;
continue; continue;
} }
if (!strncmp(arg, "--base-path=", 12)) { if (!prefixcmp(arg, "--base-path=")) {
base_path = arg+12; base_path = arg+12;
continue; continue;
} }
if (!strncmp(arg, "--interpolated-path=", 20)) { if (!prefixcmp(arg, "--interpolated-path=")) {
interpolated_path = arg+20; interpolated_path = arg+20;
continue; continue;
} }
@ -1063,11 +1073,11 @@ int main(int argc, char **argv)
user_path = ""; user_path = "";
continue; continue;
} }
if (!strncmp(arg, "--user-path=", 12)) { if (!prefixcmp(arg, "--user-path=")) {
user_path = arg + 12; user_path = arg + 12;
continue; continue;
} }
if (!strncmp(arg, "--pid-file=", 11)) { if (!prefixcmp(arg, "--pid-file=")) {
pid_file = arg + 11; pid_file = arg + 11;
continue; continue;
} }
@ -1076,27 +1086,27 @@ int main(int argc, char **argv)
log_syslog = 1; log_syslog = 1;
continue; continue;
} }
if (!strncmp(arg, "--user=", 7)) { if (!prefixcmp(arg, "--user=")) {
user_name = arg + 7; user_name = arg + 7;
continue; continue;
} }
if (!strncmp(arg, "--group=", 8)) { if (!prefixcmp(arg, "--group=")) {
group_name = arg + 8; group_name = arg + 8;
continue; continue;
} }
if (!strncmp(arg, "--enable=", 9)) { if (!prefixcmp(arg, "--enable=")) {
enable_service(arg + 9, 1); enable_service(arg + 9, 1);
continue; continue;
} }
if (!strncmp(arg, "--disable=", 10)) { if (!prefixcmp(arg, "--disable=")) {
enable_service(arg + 10, 0); enable_service(arg + 10, 0);
continue; continue;
} }
if (!strncmp(arg, "--allow-override=", 17)) { if (!prefixcmp(arg, "--allow-override=")) {
make_service_overridable(arg + 17, 1); make_service_overridable(arg + 17, 1);
continue; continue;
} }
if (!strncmp(arg, "--forbid-override=", 18)) { if (!prefixcmp(arg, "--forbid-override=")) {
make_service_overridable(arg + 18, 0); make_service_overridable(arg + 18, 0);
continue; continue;
} }

Просмотреть файл

@ -41,17 +41,27 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
path_len = ce_namelen(ce); path_len = ce_namelen(ce);
dpath = xmalloc (combine_diff_path_size (5, path_len)); dpath = xmalloc(combine_diff_path_size(5, path_len));
dpath->path = (char *) &(dpath->parent[5]); dpath->path = (char *) &(dpath->parent[5]);
dpath->next = NULL; dpath->next = NULL;
dpath->len = path_len; dpath->len = path_len;
memcpy(dpath->path, ce->name, path_len); memcpy(dpath->path, ce->name, path_len);
dpath->path[path_len] = '\0'; dpath->path[path_len] = '\0';
dpath->mode = 0;
hashclr(dpath->sha1); hashclr(dpath->sha1);
memset(&(dpath->parent[0]), 0, memset(&(dpath->parent[0]), 0,
sizeof(struct combine_diff_parent)*5); sizeof(struct combine_diff_parent)*5);
if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT && errno != ENOTDIR) {
perror(ce->name);
continue;
}
if (silent_on_removed)
continue;
}
else
dpath->mode = canon_mode(st.st_mode);
while (i < entries) { while (i < entries) {
struct cache_entry *nce = active_cache[i]; struct cache_entry *nce = active_cache[i];
@ -170,9 +180,7 @@ static int get_stat_data(struct cache_entry *ce,
} }
changed = ce_match_stat(ce, &st, 0); changed = ce_match_stat(ce, &st, 0);
if (changed) { if (changed) {
mode = create_ce_mode(st.st_mode); mode = ce_mode_from_stat(ce, st.st_mode);
if (!trust_executable_bit && S_ISREG(st.st_mode))
mode = ce->ce_mode;
sha1 = no_sha1; sha1 = no_sha1;
} }
} }

172
diff.c
Просмотреть файл

@ -77,7 +77,7 @@ int git_diff_ui_config(const char *var, const char *value)
diff_detect_rename_default = DIFF_DETECT_RENAME; diff_detect_rename_default = DIFF_DETECT_RENAME;
return 0; return 0;
} }
if (!strncmp(var, "diff.color.", 11) || !strncmp(var, "color.diff.", 11)) { if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
int slot = parse_diff_color_slot(var, 11); int slot = parse_diff_color_slot(var, 11);
color_parse(value, var, diff_colors[slot]); color_parse(value, var, diff_colors[slot]);
return 0; return 0;
@ -184,42 +184,61 @@ static void print_line_count(int count)
} }
} }
static void copy_file(int prefix, const char *data, int size) static void copy_file(int prefix, const char *data, int size,
const char *set, const char *reset)
{ {
int ch, nl_just_seen = 1; int ch, nl_just_seen = 1;
while (0 < size--) { while (0 < size--) {
ch = *data++; ch = *data++;
if (nl_just_seen) if (nl_just_seen) {
fputs(set, stdout);
putchar(prefix); putchar(prefix);
putchar(ch); }
if (ch == '\n') if (ch == '\n') {
nl_just_seen = 1; nl_just_seen = 1;
else fputs(reset, stdout);
} else
nl_just_seen = 0; nl_just_seen = 0;
putchar(ch);
} }
if (!nl_just_seen) if (!nl_just_seen)
printf("\n\\ No newline at end of file\n"); printf("%s\n\\ No newline at end of file\n", reset);
} }
static void emit_rewrite_diff(const char *name_a, static void emit_rewrite_diff(const char *name_a,
const char *name_b, const char *name_b,
struct diff_filespec *one, struct diff_filespec *one,
struct diff_filespec *two) struct diff_filespec *two,
int color_diff)
{ {
int lc_a, lc_b; int lc_a, lc_b;
const char *name_a_tab, *name_b_tab;
const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
const char *old = diff_get_color(color_diff, DIFF_FILE_OLD);
const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
const char *reset = diff_get_color(color_diff, DIFF_RESET);
name_a += (*name_a == '/');
name_b += (*name_b == '/');
name_a_tab = strchr(name_a, ' ') ? "\t" : "";
name_b_tab = strchr(name_b, ' ') ? "\t" : "";
diff_populate_filespec(one, 0); diff_populate_filespec(one, 0);
diff_populate_filespec(two, 0); diff_populate_filespec(two, 0);
lc_a = count_lines(one->data, one->size); lc_a = count_lines(one->data, one->size);
lc_b = count_lines(two->data, two->size); lc_b = count_lines(two->data, two->size);
printf("--- a/%s\n+++ b/%s\n@@ -", name_a, name_b); printf("%s--- a/%s%s%s\n%s+++ b/%s%s%s\n%s@@ -",
metainfo, name_a, name_a_tab, reset,
metainfo, name_b, name_b_tab, reset, fraginfo);
print_line_count(lc_a); print_line_count(lc_a);
printf(" +"); printf(" +");
print_line_count(lc_b); print_line_count(lc_b);
printf(" @@\n"); printf(" @@%s\n", reset);
if (lc_a) if (lc_a)
copy_file('-', one->data, one->size); copy_file('-', one->data, one->size, old, reset);
if (lc_b) if (lc_b)
copy_file('+', two->data, two->size); copy_file('+', two->data, two->size, new, reset);
} }
static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
@ -398,22 +417,16 @@ static void emit_line(const char *set, const char *reset, const char *line, int
puts(reset); puts(reset);
} }
static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len) static void emit_line_with_ws(int nparents,
const char *set, const char *reset, const char *ws,
const char *line, int len)
{ {
int col0 = ecbdata->nparents; int col0 = nparents;
int last_tab_in_indent = -1; int last_tab_in_indent = -1;
int last_space_in_indent = -1; int last_space_in_indent = -1;
int i; int i;
int tail = len; int tail = len;
int need_highlight_leading_space = 0; int need_highlight_leading_space = 0;
const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
if (!*ws) {
emit_line(set, reset, line, len);
return;
}
/* The line is a newly added line. Does it have funny leading /* The line is a newly added line. Does it have funny leading
* whitespaces? In indent, SP should never precede a TAB. * whitespaces? In indent, SP should never precede a TAB.
*/ */
@ -468,6 +481,18 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons
emit_line(set, reset, line + i, len - i); emit_line(set, reset, line + i, len - i);
} }
static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
{
const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
if (!*ws)
emit_line(set, reset, line, len);
else
emit_line_with_ws(ecbdata->nparents, set, reset, ws,
line, len);
}
static void fn_out_consume(void *priv, char *line, unsigned long len) static void fn_out_consume(void *priv, char *line, unsigned long len)
{ {
int i; int i;
@ -477,8 +502,15 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET); const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
if (ecbdata->label_path[0]) { if (ecbdata->label_path[0]) {
printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset); const char *name_a_tab, *name_b_tab;
printf("%s+++ %s%s\n", set, ecbdata->label_path[1], reset);
name_a_tab = strchr(ecbdata->label_path[0], ' ') ? "\t" : "";
name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : "";
printf("%s--- %s%s%s\n",
set, ecbdata->label_path[0], reset, name_a_tab);
printf("%s+++ %s%s%s\n",
set, ecbdata->label_path[1], reset, name_b_tab);
ecbdata->label_path[0] = ecbdata->label_path[1] = NULL; ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
} }
@ -870,30 +902,44 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options)
struct checkdiff_t { struct checkdiff_t {
struct xdiff_emit_state xm; struct xdiff_emit_state xm;
const char *filename; const char *filename;
int lineno; int lineno, color_diff;
}; };
static void checkdiff_consume(void *priv, char *line, unsigned long len) static void checkdiff_consume(void *priv, char *line, unsigned long len)
{ {
struct checkdiff_t *data = priv; struct checkdiff_t *data = priv;
const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE);
const char *reset = diff_get_color(data->color_diff, DIFF_RESET);
const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW);
if (line[0] == '+') { if (line[0] == '+') {
int i, spaces = 0; int i, spaces = 0, space_before_tab = 0, white_space_at_end = 0;
/* check space before tab */ /* check space before tab */
for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++) for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++)
if (line[i] == ' ') if (line[i] == ' ')
spaces++; spaces++;
if (line[i - 1] == '\t' && spaces) if (line[i - 1] == '\t' && spaces)
printf("%s:%d: space before tab:%.*s\n", space_before_tab = 1;
data->filename, data->lineno, (int)len, line);
/* check white space at line end */ /* check white space at line end */
if (line[len - 1] == '\n') if (line[len - 1] == '\n')
len--; len--;
if (isspace(line[len - 1])) if (isspace(line[len - 1]))
printf("%s:%d: white space at end: %.*s\n", white_space_at_end = 1;
data->filename, data->lineno, (int)len, line);
if (space_before_tab || white_space_at_end) {
printf("%s:%d: %s", data->filename, data->lineno, ws);
if (space_before_tab) {
printf("space before tab");
if (white_space_at_end)
putchar(',');
}
if (white_space_at_end)
printf("white space at end");
printf(":%s ", reset);
emit_line_with_ws(1, set, reset, ws, line, len);
}
data->lineno++; data->lineno++;
} else if (line[0] == ' ') } else if (line[0] == ' ')
@ -1020,8 +1066,8 @@ static void builtin_diff(const char *name_a,
const char *set = diff_get_color(o->color_diff, DIFF_METAINFO); const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
const char *reset = diff_get_color(o->color_diff, DIFF_RESET); const char *reset = diff_get_color(o->color_diff, DIFF_RESET);
a_one = quote_two("a/", name_a); a_one = quote_two("a/", name_a + (*name_a == '/'));
b_two = quote_two("b/", name_b); b_two = quote_two("b/", name_b + (*name_b == '/'));
lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null"; lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset); printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
@ -1050,7 +1096,8 @@ static void builtin_diff(const char *name_a,
if ((one->mode ^ two->mode) & S_IFMT) if ((one->mode ^ two->mode) & S_IFMT)
goto free_ab_and_return; goto free_ab_and_return;
if (complete_rewrite) { if (complete_rewrite) {
emit_rewrite_diff(name_a, name_b, one, two); emit_rewrite_diff(name_a, name_b, one, two,
o->color_diff);
goto free_ab_and_return; goto free_ab_and_return;
} }
} }
@ -1085,9 +1132,9 @@ static void builtin_diff(const char *name_a,
xecfg.flags = XDL_EMIT_FUNCNAMES; xecfg.flags = XDL_EMIT_FUNCNAMES;
if (!diffopts) if (!diffopts)
; ;
else if (!strncmp(diffopts, "--unified=", 10)) else if (!prefixcmp(diffopts, "--unified="))
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10); xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
else if (!strncmp(diffopts, "-u", 2)) else if (!prefixcmp(diffopts, "-u"))
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10); xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
ecb.outf = xdiff_outf; ecb.outf = xdiff_outf;
ecb.priv = &ecbdata; ecb.priv = &ecbdata;
@ -1151,7 +1198,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
static void builtin_checkdiff(const char *name_a, const char *name_b, static void builtin_checkdiff(const char *name_a, const char *name_b,
struct diff_filespec *one, struct diff_filespec *one,
struct diff_filespec *two) struct diff_filespec *two, struct diff_options *o)
{ {
mmfile_t mf1, mf2; mmfile_t mf1, mf2;
struct checkdiff_t data; struct checkdiff_t data;
@ -1163,6 +1210,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
data.xm.consume = checkdiff_consume; data.xm.consume = checkdiff_consume;
data.filename = name_b ? name_b : name_a; data.filename = name_b ? name_b : name_a;
data.lineno = 0; data.lineno = 0;
data.color_diff = o->color_diff;
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
die("unable to read files to diff"); die("unable to read files to diff");
@ -1332,6 +1380,9 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
reuse_worktree_file(s->path, s->sha1, 0)) { reuse_worktree_file(s->path, s->sha1, 0)) {
struct stat st; struct stat st;
int fd; int fd;
char *buf;
unsigned long size;
if (lstat(s->path, &st) < 0) { if (lstat(s->path, &st) < 0) {
if (errno == ENOENT) { if (errno == ENOENT) {
err_empty: err_empty:
@ -1364,10 +1415,22 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0); s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd); close(fd);
s->should_munmap = 1; s->should_munmap = 1;
/* FIXME! CRLF -> LF conversion goes here, based on "s->path" */
/*
* Convert from working tree format to canonical git format
*/
buf = s->data;
size = s->size;
if (convert_to_git(s->path, &buf, &size)) {
munmap(s->data, s->size);
s->should_munmap = 0;
s->data = buf;
s->size = size;
s->should_free = 1;
}
} }
else { else {
char type[20]; enum object_type type;
struct sha1_size_cache *e; struct sha1_size_cache *e;
if (size_only) { if (size_only) {
@ -1376,11 +1439,12 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
s->size = e->size; s->size = e->size;
return 0; return 0;
} }
if (!sha1_object_info(s->sha1, type, &s->size)) type = sha1_object_info(s->sha1, &s->size);
if (type < 0)
locate_size_cache(s->sha1, 0, s->size); locate_size_cache(s->sha1, 0, s->size);
} }
else { else {
s->data = read_sha1_file(s->sha1, type, &s->size); s->data = read_sha1_file(s->sha1, &type, &s->size);
s->should_free = 1; s->should_free = 1;
} }
} }
@ -1773,7 +1837,7 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
diff_fill_sha1_info(p->one); diff_fill_sha1_info(p->one);
diff_fill_sha1_info(p->two); diff_fill_sha1_info(p->two);
builtin_checkdiff(name, other, p->one, p->two); builtin_checkdiff(name, other, p->one, p->two, o);
} }
void diff_setup(struct diff_options *options) void diff_setup(struct diff_options *options)
@ -1922,7 +1986,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
else if (!strcmp(arg, "--shortstat")) { else if (!strcmp(arg, "--shortstat")) {
options->output_format |= DIFF_FORMAT_SHORTSTAT; options->output_format |= DIFF_FORMAT_SHORTSTAT;
} }
else if (!strncmp(arg, "--stat", 6)) { else if (!prefixcmp(arg, "--stat")) {
char *end; char *end;
int width = options->stat_width; int width = options->stat_width;
int name_width = options->stat_name_width; int name_width = options->stat_name_width;
@ -1931,9 +1995,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
switch (*arg) { switch (*arg) {
case '-': case '-':
if (!strncmp(arg, "-width=", 7)) if (!prefixcmp(arg, "-width="))
width = strtoul(arg + 7, &end, 10); width = strtoul(arg + 7, &end, 10);
else if (!strncmp(arg, "-name-width=", 12)) else if (!prefixcmp(arg, "-name-width="))
name_width = strtoul(arg + 12, &end, 10); name_width = strtoul(arg + 12, &end, 10);
break; break;
case '=': case '=':
@ -1958,7 +2022,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
} }
else if (!strcmp(arg, "-z")) else if (!strcmp(arg, "-z"))
options->line_termination = 0; options->line_termination = 0;
else if (!strncmp(arg, "-l", 2)) else if (!prefixcmp(arg, "-l"))
options->rename_limit = strtoul(arg+2, NULL, 10); options->rename_limit = strtoul(arg+2, NULL, 10);
else if (!strcmp(arg, "--full-index")) else if (!strcmp(arg, "--full-index"))
options->full_index = 1; options->full_index = 1;
@ -1975,31 +2039,31 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->output_format |= DIFF_FORMAT_NAME_STATUS; options->output_format |= DIFF_FORMAT_NAME_STATUS;
else if (!strcmp(arg, "-R")) else if (!strcmp(arg, "-R"))
options->reverse_diff = 1; options->reverse_diff = 1;
else if (!strncmp(arg, "-S", 2)) else if (!prefixcmp(arg, "-S"))
options->pickaxe = arg + 2; options->pickaxe = arg + 2;
else if (!strcmp(arg, "-s")) { else if (!strcmp(arg, "-s")) {
options->output_format |= DIFF_FORMAT_NO_OUTPUT; options->output_format |= DIFF_FORMAT_NO_OUTPUT;
} }
else if (!strncmp(arg, "-O", 2)) else if (!prefixcmp(arg, "-O"))
options->orderfile = arg + 2; options->orderfile = arg + 2;
else if (!strncmp(arg, "--diff-filter=", 14)) else if (!prefixcmp(arg, "--diff-filter="))
options->filter = arg + 14; options->filter = arg + 14;
else if (!strcmp(arg, "--pickaxe-all")) else if (!strcmp(arg, "--pickaxe-all"))
options->pickaxe_opts = DIFF_PICKAXE_ALL; options->pickaxe_opts = DIFF_PICKAXE_ALL;
else if (!strcmp(arg, "--pickaxe-regex")) else if (!strcmp(arg, "--pickaxe-regex"))
options->pickaxe_opts = DIFF_PICKAXE_REGEX; options->pickaxe_opts = DIFF_PICKAXE_REGEX;
else if (!strncmp(arg, "-B", 2)) { else if (!prefixcmp(arg, "-B")) {
if ((options->break_opt = if ((options->break_opt =
diff_scoreopt_parse(arg)) == -1) diff_scoreopt_parse(arg)) == -1)
return -1; return -1;
} }
else if (!strncmp(arg, "-M", 2)) { else if (!prefixcmp(arg, "-M")) {
if ((options->rename_score = if ((options->rename_score =
diff_scoreopt_parse(arg)) == -1) diff_scoreopt_parse(arg)) == -1)
return -1; return -1;
options->detect_rename = DIFF_DETECT_RENAME; options->detect_rename = DIFF_DETECT_RENAME;
} }
else if (!strncmp(arg, "-C", 2)) { else if (!prefixcmp(arg, "-C")) {
if ((options->rename_score = if ((options->rename_score =
diff_scoreopt_parse(arg)) == -1) diff_scoreopt_parse(arg)) == -1)
return -1; return -1;
@ -2009,7 +2073,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->find_copies_harder = 1; options->find_copies_harder = 1;
else if (!strcmp(arg, "--abbrev")) else if (!strcmp(arg, "--abbrev"))
options->abbrev = DEFAULT_ABBREV; options->abbrev = DEFAULT_ABBREV;
else if (!strncmp(arg, "--abbrev=", 9)) { else if (!prefixcmp(arg, "--abbrev=")) {
options->abbrev = strtoul(arg + 9, NULL, 10); options->abbrev = strtoul(arg + 9, NULL, 10);
if (options->abbrev < MINIMUM_ABBREV) if (options->abbrev < MINIMUM_ABBREV)
options->abbrev = MINIMUM_ABBREV; options->abbrev = MINIMUM_ABBREV;
@ -2024,6 +2088,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->xdl_opts |= XDF_IGNORE_WHITESPACE; options->xdl_opts |= XDF_IGNORE_WHITESPACE;
else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change")) else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE; options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
else if (!strcmp(arg, "--ignore-space-at-eol"))
options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
else if (!strcmp(arg, "--color-words")) else if (!strcmp(arg, "--color-words"))
options->color_diff = options->color_diff_words = 1; options->color_diff = options->color_diff_words = 1;
else if (!strcmp(arg, "--no-renames")) else if (!strcmp(arg, "--no-renames"))
@ -2516,7 +2582,7 @@ static void patch_id_consume(void *priv, char *line, unsigned long len)
int new_len; int new_len;
/* Ignore line numbers when computing the SHA1 of the patch */ /* Ignore line numbers when computing the SHA1 of the patch */
if (!strncmp(line, "@@ -", 4)) if (!prefixcmp(line, "@@ -"))
return; return;
new_len = remove_space(line, len); new_len = remove_space(line, len);

22
entry.c
Просмотреть файл

@ -68,16 +68,19 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
void *new; void *new;
unsigned long size; unsigned long size;
long wrote; long wrote;
char type[20]; enum object_type type;
new = read_sha1_file(ce->sha1, type, &size); new = read_sha1_file(ce->sha1, &type, &size);
if (!new || strcmp(type, blob_type)) { if (!new || type != OBJ_BLOB) {
if (new) if (new)
free(new); free(new);
return error("git-checkout-index: unable to read sha1 file of %s (%s)", return error("git-checkout-index: unable to read sha1 file of %s (%s)",
path, sha1_to_hex(ce->sha1)); path, sha1_to_hex(ce->sha1));
} }
switch (ntohl(ce->ce_mode) & S_IFMT) { switch (ntohl(ce->ce_mode) & S_IFMT) {
char *buf;
unsigned long nsize;
case S_IFREG: case S_IFREG:
if (to_tempfile) { if (to_tempfile) {
strcpy(path, ".merge_file_XXXXXX"); strcpy(path, ".merge_file_XXXXXX");
@ -89,7 +92,18 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
return error("git-checkout-index: unable to create file %s (%s)", return error("git-checkout-index: unable to create file %s (%s)",
path, strerror(errno)); path, strerror(errno));
} }
/* FIXME: LF -> CRLF conversion goes here, based on "ce->name" */
/*
* Convert from git internal format to working tree format
*/
buf = new;
nsize = size;
if (convert_to_working_tree(ce->name, &buf, &nsize)) {
free(new);
new = buf;
size = nsize;
}
wrote = write_in_full(fd, new, size); wrote = write_in_full(fd, new, size);
close(fd); close(fd);
free(new); free(new);

Просмотреть файл

@ -28,6 +28,7 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT; size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
int pager_in_use; int pager_in_use;
int pager_use_color = 1; int pager_use_color = 1;
int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */
static const char *git_dir; static const char *git_dir;
static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file; static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;

Просмотреть файл

@ -56,7 +56,7 @@ int execv_git_cmd(const char **argv)
len = strlen(git_command); len = strlen(git_command);
/* Trivial cleanup */ /* Trivial cleanup */
while (!strncmp(exec_dir, "./", 2)) { while (!prefixcmp(exec_dir, "./")) {
exec_dir += 2; exec_dir += 2;
while (*exec_dir == '/') while (*exec_dir == '/')
exec_dir++; exec_dir++;

Просмотреть файл

@ -133,6 +133,10 @@ Format of STDIN stream:
#define PACK_ID_BITS 16 #define PACK_ID_BITS 16
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1) #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
#ifndef PRIuMAX
#define PRIuMAX "llu"
#endif
struct object_entry struct object_entry
{ {
struct object_entry *next; struct object_entry *next;
@ -475,7 +479,7 @@ static struct object_entry *find_mark(uintmax_t idnum)
oe = s->data.marked[idnum]; oe = s->data.marked[idnum];
} }
if (!oe) if (!oe)
die("mark :%ju not declared", orig_idnum); die("mark :%" PRIuMAX " not declared", orig_idnum);
return oe; return oe;
} }
@ -887,7 +891,7 @@ static int store_object(
SHA_CTX c; SHA_CTX c;
z_stream s; z_stream s;
hdrlen = sprintf((char*)hdr,"%s %lu", type_names[type], hdrlen = sprintf((char*)hdr,"%s %lu", typename(type),
(unsigned long)datlen) + 1; (unsigned long)datlen) + 1;
SHA1_Init(&c); SHA1_Init(&c);
SHA1_Update(&c, hdr, hdrlen); SHA1_Update(&c, hdr, hdrlen);
@ -1004,11 +1008,11 @@ static void *gfi_unpack_entry(
struct object_entry *oe, struct object_entry *oe,
unsigned long *sizep) unsigned long *sizep)
{ {
static char type[20]; enum object_type type;
struct packed_git *p = all_packs[oe->pack_id]; struct packed_git *p = all_packs[oe->pack_id];
if (p == pack_data) if (p == pack_data)
p->pack_size = pack_size + 20; p->pack_size = pack_size + 20;
return unpack_entry(p, oe->offset, type, sizep); return unpack_entry(p, oe->offset, &type, sizep);
} }
static const char *get_mode(const char *str, uint16_t *modep) static const char *get_mode(const char *str, uint16_t *modep)
@ -1045,9 +1049,9 @@ static void load_tree(struct tree_entry *root)
t->delta_depth = 0; t->delta_depth = 0;
buf = gfi_unpack_entry(myoe, &size); buf = gfi_unpack_entry(myoe, &size);
} else { } else {
char type[20]; enum object_type type;
buf = read_sha1_file(sha1, type, &size); buf = read_sha1_file(sha1, &type, &size);
if (!buf || strcmp(type, tree_type)) if (!buf || type != OBJ_TREE)
die("Can't load tree %s", sha1_to_hex(sha1)); die("Can't load tree %s", sha1_to_hex(sha1));
} }
@ -1308,7 +1312,7 @@ static int update_branch(struct branch *b)
return error("Branch %s is missing commits.", b->name); return error("Branch %s is missing commits.", b->name);
} }
if (!in_merge_bases(old_cmit, new_cmit)) { if (!in_merge_bases(old_cmit, &new_cmit, 1)) {
unlock_ref(lock); unlock_ref(lock);
warn("Not updating %s" warn("Not updating %s"
" (new tip %s does not contain %s)", " (new tip %s does not contain %s)",
@ -1361,7 +1365,7 @@ static void dump_marks_helper(FILE *f,
} else { } else {
for (k = 0; k < 1024; k++) { for (k = 0; k < 1024; k++) {
if (m->data.marked[k]) if (m->data.marked[k])
fprintf(f, ":%ju %s\n", base + k, fprintf(f, ":%" PRIuMAX " %s\n", base + k,
sha1_to_hex(m->data.marked[k]->sha1)); sha1_to_hex(m->data.marked[k]->sha1));
} }
} }
@ -1388,7 +1392,7 @@ static void read_next_command(void)
static void cmd_mark(void) static void cmd_mark(void)
{ {
if (!strncmp("mark :", command_buf.buf, 6)) { if (!prefixcmp(command_buf.buf, "mark :")) {
next_mark = strtoumax(command_buf.buf + 6, NULL, 10); next_mark = strtoumax(command_buf.buf + 6, NULL, 10);
read_next_command(); read_next_command();
} }
@ -1401,10 +1405,10 @@ static void *cmd_data (size_t *size)
size_t length; size_t length;
char *buffer; char *buffer;
if (strncmp("data ", command_buf.buf, 5)) if (prefixcmp(command_buf.buf, "data "))
die("Expected 'data n' command, found: %s", command_buf.buf); die("Expected 'data n' command, found: %s", command_buf.buf);
if (!strncmp("<<", command_buf.buf + 5, 2)) { if (!prefixcmp(command_buf.buf + 5, "<<")) {
char *term = xstrdup(command_buf.buf + 5 + 2); char *term = xstrdup(command_buf.buf + 5 + 2);
size_t sz = 8192, term_len = command_buf.len - 5 - 2; size_t sz = 8192, term_len = command_buf.len - 5 - 2;
length = 0; length = 0;
@ -1569,7 +1573,6 @@ static void file_change_m(struct branch *b)
struct object_entry *oe = oe; struct object_entry *oe = oe;
unsigned char sha1[20]; unsigned char sha1[20];
uint16_t mode, inline_data = 0; uint16_t mode, inline_data = 0;
char type[20];
p = get_mode(p, &mode); p = get_mode(p, &mode);
if (!p) if (!p)
@ -1591,7 +1594,7 @@ static void file_change_m(struct branch *b)
oe = find_mark(strtoumax(p + 1, &x, 10)); oe = find_mark(strtoumax(p + 1, &x, 10));
hashcpy(sha1, oe->sha1); hashcpy(sha1, oe->sha1);
p = x; p = x;
} else if (!strncmp("inline", p, 6)) { } else if (!prefixcmp(p, "inline")) {
inline_data = 1; inline_data = 1;
p += 6; p += 6;
} else { } else {
@ -1622,13 +1625,14 @@ static void file_change_m(struct branch *b)
} else if (oe) { } else if (oe) {
if (oe->type != OBJ_BLOB) if (oe->type != OBJ_BLOB)
die("Not a blob (actually a %s): %s", die("Not a blob (actually a %s): %s",
command_buf.buf, type_names[oe->type]); command_buf.buf, typename(oe->type));
} else { } else {
if (sha1_object_info(sha1, type, NULL)) enum object_type type = sha1_object_info(sha1, NULL);
if (type < 0)
die("Blob not found: %s", command_buf.buf); die("Blob not found: %s", command_buf.buf);
if (strcmp(blob_type, type)) if (type != OBJ_BLOB)
die("Not a blob (actually a %s): %s", die("Not a blob (actually a %s): %s",
command_buf.buf, type); typename(type), command_buf.buf);
} }
tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode); tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode);
@ -1664,7 +1668,7 @@ static void cmd_from(struct branch *b)
const char *from; const char *from;
struct branch *s; struct branch *s;
if (strncmp("from ", command_buf.buf, 5)) if (prefixcmp(command_buf.buf, "from "))
return; return;
if (b->branch_tree.tree) { if (b->branch_tree.tree) {
@ -1687,7 +1691,7 @@ static void cmd_from(struct branch *b)
unsigned long size; unsigned long size;
char *buf; char *buf;
if (oe->type != OBJ_COMMIT) if (oe->type != OBJ_COMMIT)
die("Mark :%ju not a commit", idnum); die("Mark :%" PRIuMAX " not a commit", idnum);
hashcpy(b->sha1, oe->sha1); hashcpy(b->sha1, oe->sha1);
buf = gfi_unpack_entry(oe, &size); buf = gfi_unpack_entry(oe, &size);
if (!buf || size < 46) if (!buf || size < 46)
@ -1707,7 +1711,7 @@ static void cmd_from(struct branch *b)
char *buf; char *buf;
buf = read_object_with_reference(b->sha1, buf = read_object_with_reference(b->sha1,
type_names[OBJ_COMMIT], &size, b->sha1); commit_type, &size, b->sha1);
if (!buf || size < 46) if (!buf || size < 46)
die("Not a valid commit: %s", from); die("Not a valid commit: %s", from);
if (memcmp("tree ", buf, 5) if (memcmp("tree ", buf, 5)
@ -1730,7 +1734,7 @@ static struct hash_list *cmd_merge(unsigned int *count)
struct branch *s; struct branch *s;
*count = 0; *count = 0;
while (!strncmp("merge ", command_buf.buf, 6)) { while (!prefixcmp(command_buf.buf, "merge ")) {
from = strchr(command_buf.buf, ' ') + 1; from = strchr(command_buf.buf, ' ') + 1;
n = xmalloc(sizeof(*n)); n = xmalloc(sizeof(*n));
s = lookup_branch(from); s = lookup_branch(from);
@ -1740,7 +1744,7 @@ static struct hash_list *cmd_merge(unsigned int *count)
uintmax_t idnum = strtoumax(from + 1, NULL, 10); uintmax_t idnum = strtoumax(from + 1, NULL, 10);
struct object_entry *oe = find_mark(idnum); struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT) if (oe->type != OBJ_COMMIT)
die("Mark :%ju not a commit", idnum); die("Mark :%" PRIuMAX " not a commit", idnum);
hashcpy(n->sha1, oe->sha1); hashcpy(n->sha1, oe->sha1);
} else if (get_sha1(from, n->sha1)) } else if (get_sha1(from, n->sha1))
die("Invalid ref name or SHA1 expression: %s", from); die("Invalid ref name or SHA1 expression: %s", from);
@ -1776,11 +1780,11 @@ static void cmd_new_commit(void)
read_next_command(); read_next_command();
cmd_mark(); cmd_mark();
if (!strncmp("author ", command_buf.buf, 7)) { if (!prefixcmp(command_buf.buf, "author ")) {
author = parse_ident(command_buf.buf + 7); author = parse_ident(command_buf.buf + 7);
read_next_command(); read_next_command();
} }
if (!strncmp("committer ", command_buf.buf, 10)) { if (!prefixcmp(command_buf.buf, "committer ")) {
committer = parse_ident(command_buf.buf + 10); committer = parse_ident(command_buf.buf + 10);
read_next_command(); read_next_command();
} }
@ -1801,9 +1805,9 @@ static void cmd_new_commit(void)
for (;;) { for (;;) {
if (1 == command_buf.len) if (1 == command_buf.len)
break; break;
else if (!strncmp("M ", command_buf.buf, 2)) else if (!prefixcmp(command_buf.buf, "M "))
file_change_m(b); file_change_m(b);
else if (!strncmp("D ", command_buf.buf, 2)) else if (!prefixcmp(command_buf.buf, "D "))
file_change_d(b); file_change_d(b);
else if (!strcmp("deleteall", command_buf.buf)) else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b); file_change_deleteall(b);
@ -1873,7 +1877,7 @@ static void cmd_new_tag(void)
read_next_command(); read_next_command();
/* from ... */ /* from ... */
if (strncmp("from ", command_buf.buf, 5)) if (prefixcmp(command_buf.buf, "from "))
die("Expected from command, got %s", command_buf.buf); die("Expected from command, got %s", command_buf.buf);
from = strchr(command_buf.buf, ' ') + 1; from = strchr(command_buf.buf, ' ') + 1;
s = lookup_branch(from); s = lookup_branch(from);
@ -1884,14 +1888,14 @@ static void cmd_new_tag(void)
from_mark = strtoumax(from + 1, NULL, 10); from_mark = strtoumax(from + 1, NULL, 10);
oe = find_mark(from_mark); oe = find_mark(from_mark);
if (oe->type != OBJ_COMMIT) if (oe->type != OBJ_COMMIT)
die("Mark :%ju not a commit", from_mark); die("Mark :%" PRIuMAX " not a commit", from_mark);
hashcpy(sha1, oe->sha1); hashcpy(sha1, oe->sha1);
} else if (!get_sha1(from, sha1)) { } else if (!get_sha1(from, sha1)) {
unsigned long size; unsigned long size;
char *buf; char *buf;
buf = read_object_with_reference(sha1, buf = read_object_with_reference(sha1,
type_names[OBJ_COMMIT], &size, sha1); commit_type, &size, sha1);
if (!buf || size < 46) if (!buf || size < 46)
die("Not a valid commit: %s", from); die("Not a valid commit: %s", from);
free(buf); free(buf);
@ -1900,7 +1904,7 @@ static void cmd_new_tag(void)
read_next_command(); read_next_command();
/* tagger ... */ /* tagger ... */
if (strncmp("tagger ", command_buf.buf, 7)) if (prefixcmp(command_buf.buf, "tagger "))
die("Expected tagger command, got %s", command_buf.buf); die("Expected tagger command, got %s", command_buf.buf);
tagger = parse_ident(command_buf.buf + 7); tagger = parse_ident(command_buf.buf + 7);
@ -1912,7 +1916,7 @@ static void cmd_new_tag(void)
size_dbuf(&new_data, 67+strlen(t->name)+strlen(tagger)+msglen); size_dbuf(&new_data, 67+strlen(t->name)+strlen(tagger)+msglen);
sp = new_data.buffer; sp = new_data.buffer;
sp += sprintf(sp, "object %s\n", sha1_to_hex(sha1)); sp += sprintf(sp, "object %s\n", sha1_to_hex(sha1));
sp += sprintf(sp, "type %s\n", type_names[OBJ_COMMIT]); sp += sprintf(sp, "type %s\n", commit_type);
sp += sprintf(sp, "tag %s\n", t->name); sp += sprintf(sp, "tag %s\n", t->name);
sp += sprintf(sp, "tagger %s\n", tagger); sp += sprintf(sp, "tagger %s\n", tagger);
*sp++ = '\n'; *sp++ = '\n';
@ -1977,7 +1981,7 @@ int main(int argc, const char **argv)
if (*a != '-' || !strcmp(a, "--")) if (*a != '-' || !strcmp(a, "--"))
break; break;
else if (!strncmp(a, "--date-format=", 14)) { else if (!prefixcmp(a, "--date-format=")) {
const char *fmt = a + 14; const char *fmt = a + 14;
if (!strcmp(fmt, "raw")) if (!strcmp(fmt, "raw"))
whenspec = WHENSPEC_RAW; whenspec = WHENSPEC_RAW;
@ -1988,15 +1992,15 @@ int main(int argc, const char **argv)
else else
die("unknown --date-format argument %s", fmt); die("unknown --date-format argument %s", fmt);
} }
else if (!strncmp(a, "--max-pack-size=", 16)) else if (!prefixcmp(a, "--max-pack-size="))
max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024; max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024;
else if (!strncmp(a, "--depth=", 8)) else if (!prefixcmp(a, "--depth="))
max_depth = strtoul(a + 8, NULL, 0); max_depth = strtoul(a + 8, NULL, 0);
else if (!strncmp(a, "--active-branches=", 18)) else if (!prefixcmp(a, "--active-branches="))
max_active_branches = strtoul(a + 18, NULL, 0); max_active_branches = strtoul(a + 18, NULL, 0);
else if (!strncmp(a, "--export-marks=", 15)) else if (!prefixcmp(a, "--export-marks="))
mark_file = a + 15; mark_file = a + 15;
else if (!strncmp(a, "--export-pack-edges=", 20)) { else if (!prefixcmp(a, "--export-pack-edges=")) {
if (pack_edges) if (pack_edges)
fclose(pack_edges); fclose(pack_edges);
pack_edges = fopen(a + 20, "a"); pack_edges = fopen(a + 20, "a");
@ -2029,11 +2033,11 @@ int main(int argc, const char **argv)
break; break;
else if (!strcmp("blob", command_buf.buf)) else if (!strcmp("blob", command_buf.buf))
cmd_new_blob(); cmd_new_blob();
else if (!strncmp("commit ", command_buf.buf, 7)) else if (!prefixcmp(command_buf.buf, "commit "))
cmd_new_commit(); cmd_new_commit();
else if (!strncmp("tag ", command_buf.buf, 4)) else if (!prefixcmp(command_buf.buf, "tag "))
cmd_new_tag(); cmd_new_tag();
else if (!strncmp("reset ", command_buf.buf, 6)) else if (!prefixcmp(command_buf.buf, "reset "))
cmd_reset_branch(); cmd_reset_branch();
else if (!strcmp("checkpoint", command_buf.buf)) else if (!strcmp("checkpoint", command_buf.buf))
cmd_checkpoint(); cmd_checkpoint();
@ -2059,18 +2063,18 @@ int main(int argc, const char **argv)
fprintf(stderr, "%s statistics:\n", argv[0]); fprintf(stderr, "%s statistics:\n", argv[0]);
fprintf(stderr, "---------------------------------------------------------------------\n"); fprintf(stderr, "---------------------------------------------------------------------\n");
fprintf(stderr, "Alloc'd objects: %10ju\n", alloc_count); fprintf(stderr, "Alloc'd objects: %10" PRIuMAX "\n", alloc_count);
fprintf(stderr, "Total objects: %10ju (%10ju duplicates )\n", total_count, duplicate_count); fprintf(stderr, "Total objects: %10" PRIuMAX " (%10" PRIuMAX " duplicates )\n", total_count, duplicate_count);
fprintf(stderr, " blobs : %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_BLOB], duplicate_count_by_type[OBJ_BLOB], delta_count_by_type[OBJ_BLOB]); fprintf(stderr, " blobs : %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_BLOB], duplicate_count_by_type[OBJ_BLOB], delta_count_by_type[OBJ_BLOB]);
fprintf(stderr, " trees : %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_TREE], duplicate_count_by_type[OBJ_TREE], delta_count_by_type[OBJ_TREE]); fprintf(stderr, " trees : %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_TREE], duplicate_count_by_type[OBJ_TREE], delta_count_by_type[OBJ_TREE]);
fprintf(stderr, " commits: %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_COMMIT], duplicate_count_by_type[OBJ_COMMIT], delta_count_by_type[OBJ_COMMIT]); fprintf(stderr, " commits: %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_COMMIT], duplicate_count_by_type[OBJ_COMMIT], delta_count_by_type[OBJ_COMMIT]);
fprintf(stderr, " tags : %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_TAG], duplicate_count_by_type[OBJ_TAG], delta_count_by_type[OBJ_TAG]); fprintf(stderr, " tags : %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_TAG], duplicate_count_by_type[OBJ_TAG], delta_count_by_type[OBJ_TAG]);
fprintf(stderr, "Total branches: %10lu (%10lu loads )\n", branch_count, branch_load_count); fprintf(stderr, "Total branches: %10lu (%10lu loads )\n", branch_count, branch_load_count);
fprintf(stderr, " marks: %10ju (%10ju unique )\n", (((uintmax_t)1) << marks->shift) * 1024, marks_set_count); fprintf(stderr, " marks: %10" PRIuMAX " (%10" PRIuMAX " unique )\n", (((uintmax_t)1) << marks->shift) * 1024, marks_set_count);
fprintf(stderr, " atoms: %10u\n", atom_cnt); fprintf(stderr, " atoms: %10u\n", atom_cnt);
fprintf(stderr, "Memory total: %10ju KiB\n", (total_allocd + alloc_count*sizeof(struct object_entry))/1024); fprintf(stderr, "Memory total: %10" PRIuMAX " KiB\n", (total_allocd + alloc_count*sizeof(struct object_entry))/1024);
fprintf(stderr, " pools: %10lu KiB\n", (unsigned long)(total_allocd/1024)); fprintf(stderr, " pools: %10lu KiB\n", (unsigned long)(total_allocd/1024));
fprintf(stderr, " objects: %10ju KiB\n", (alloc_count*sizeof(struct object_entry))/1024); fprintf(stderr, " objects: %10" PRIuMAX " KiB\n", (alloc_count*sizeof(struct object_entry))/1024);
fprintf(stderr, "---------------------------------------------------------------------\n"); fprintf(stderr, "---------------------------------------------------------------------\n");
pack_report(); pack_report();
fprintf(stderr, "---------------------------------------------------------------------\n"); fprintf(stderr, "---------------------------------------------------------------------\n");

Просмотреть файл

@ -198,13 +198,13 @@ static int find_common(int fd[2], unsigned char *result_sha1,
int len; int len;
while ((len = packet_read_line(fd[0], line, sizeof(line)))) { while ((len = packet_read_line(fd[0], line, sizeof(line)))) {
if (!strncmp("shallow ", line, 8)) { if (!prefixcmp(line, "shallow ")) {
if (get_sha1_hex(line + 8, sha1)) if (get_sha1_hex(line + 8, sha1))
die("invalid shallow line: %s", line); die("invalid shallow line: %s", line);
register_shallow(sha1); register_shallow(sha1);
continue; continue;
} }
if (!strncmp("unshallow ", line, 10)) { if (!prefixcmp(line, "unshallow ")) {
if (get_sha1_hex(line + 10, sha1)) if (get_sha1_hex(line + 10, sha1))
die("invalid unshallow line: %s", line); die("invalid unshallow line: %s", line);
if (!lookup_object(sha1)) if (!lookup_object(sha1))
@ -346,7 +346,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
check_ref_format(ref->name + 5)) check_ref_format(ref->name + 5))
; /* trash */ ; /* trash */
else if (fetch_all && else if (fetch_all &&
(!depth || strncmp(ref->name, "refs/tags/", 10) )) { (!depth || prefixcmp(ref->name, "refs/tags/") )) {
*newtail = ref; *newtail = ref;
ref->next = NULL; ref->next = NULL;
newtail = &ref->next; newtail = &ref->next;
@ -683,11 +683,11 @@ int main(int argc, char **argv)
char *arg = argv[i]; char *arg = argv[i];
if (*arg == '-') { if (*arg == '-') {
if (!strncmp("--upload-pack=", arg, 14)) { if (!prefixcmp(arg, "--upload-pack=")) {
uploadpack = arg + 14; uploadpack = arg + 14;
continue; continue;
} }
if (!strncmp("--exec=", arg, 7)) { if (!prefixcmp(arg, "--exec=")) {
uploadpack = arg + 7; uploadpack = arg + 7;
continue; continue;
} }
@ -712,7 +712,7 @@ int main(int argc, char **argv)
verbose = 1; verbose = 1;
continue; continue;
} }
if (!strncmp("--depth=", arg, 8)) { if (!prefixcmp(arg, "--depth=")) {
depth = strtol(arg + 8, NULL, 0); depth = strtol(arg + 8, NULL, 0);
if (stat(git_path("shallow"), &st)) if (stat(git_path("shallow"), &st))
st.st_mtime = 0; st.st_mtime = 0;

Просмотреть файл

@ -66,7 +66,7 @@ fall_back_3way () {
git-update-index -z --index-info <"$dotest/patch-merge-index-info" && git-update-index -z --index-info <"$dotest/patch-merge-index-info" &&
GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
git-write-tree >"$dotest/patch-merge-base+" || git-write-tree >"$dotest/patch-merge-base+" ||
cannot_fallback "Patch does not record usable index information." cannot_fallback "Repository lacks necessary blobs to fall back on 3-way merge."
echo Using index info to reconstruct a base tree... echo Using index info to reconstruct a base tree...
if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше