mirror of
https://github.com/git/git.git
synced 2026-04-02 04:50:12 +02:00
Merge branch 'master' of git://repo.or.cz/alt-git
This commit is contained in:
@@ -22,6 +22,13 @@ branch pointed at by its HEAD, gets a large warning. You can choose what
|
||||
should happen upon such a push by setting the configuration variable
|
||||
receive.denyDeleteCurrent in the receiving repository.
|
||||
|
||||
When the user does not tell "git push" what to push, it has always
|
||||
pushed matching refs. For some people it is unexpected, and a new
|
||||
configuration variable push.default has been introduced to allow
|
||||
changing a different default behaviour. To advertise the new feature,
|
||||
a big warning is issued if this is not configured and a git push without
|
||||
arguments is attempted.
|
||||
|
||||
|
||||
Updates since v1.6.2
|
||||
--------------------
|
||||
@@ -39,6 +46,9 @@ Updates since v1.6.2
|
||||
repositories. It may not be useful in practice; meant primarily for
|
||||
testing.
|
||||
|
||||
* http transport learned to prompt and use password when fetching from or
|
||||
pushing to http://user@host.xz/ URL.
|
||||
|
||||
* (msysgit) progress output that is sent over the sideband protocol can
|
||||
be handled appropriately in Windows console.
|
||||
|
||||
@@ -92,6 +102,8 @@ Updates since v1.6.2
|
||||
|
||||
* Test scripts can be run under valgrind.
|
||||
|
||||
* Test scripts can be run with installed git.
|
||||
|
||||
* Makefile learned 'coverage' option to run the test suites with
|
||||
coverage tracking enabled.
|
||||
|
||||
@@ -104,11 +116,20 @@ release, unless otherwise noted.
|
||||
Here are fixes that this release has, but have not been backported to
|
||||
v1.6.2.X series.
|
||||
|
||||
* "git-blame -S" did not quite work near the commits that were given
|
||||
on the command line correctly (jc/maint-1.6.0-blame-s).
|
||||
|
||||
* The initial checkout did not read the attributes from the .gitattribute
|
||||
file that is being checked out.
|
||||
|
||||
* git-diff feeds files in work-tree representation to external diff and
|
||||
textconv (js/maint-diff-temp-smudge).
|
||||
|
||||
* git-gc spent excessive amount of time to decide if an object appears
|
||||
in a locally existing pack (if needed, backport by merging 69e020a).
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.2.1-213-g7d4e3a7
|
||||
O=v1.6.2.1-399-gaa72a14
|
||||
echo O=$(git describe master)
|
||||
git shortlog --no-merges $O..master ^maint
|
||||
|
||||
@@ -1194,6 +1194,24 @@ pull.octopus::
|
||||
pull.twohead::
|
||||
The default merge strategy to use when pulling a single branch.
|
||||
|
||||
push.default::
|
||||
Defines the action git push should take if no refspec is given
|
||||
on the command line, no refspec is configured in the remote, and
|
||||
no refspec is implied by any of the options given on the command
|
||||
line.
|
||||
+
|
||||
The term `current remote` means the remote configured for the current
|
||||
branch, or `origin` if no remote is configured. `origin` is also used
|
||||
if you are not on any branch. Possible values are:
|
||||
+
|
||||
* `nothing` do not push anything.
|
||||
* `matching` push all matching branches to the current remote.
|
||||
All branches having the same name in both ends are considered to be
|
||||
matching. This is the current default value.
|
||||
* `tracking` push the current branch to the branch it is tracking.
|
||||
* `current` push the current branch to a branch of the same name on the
|
||||
current remote.
|
||||
|
||||
rebase.stat::
|
||||
Whether to show a diffstat of what changed upstream since the last
|
||||
rebase. False by default.
|
||||
|
||||
@@ -81,7 +81,7 @@ will have been left with the first bad kernel revision in "refs/bisect/bad".
|
||||
Bisect reset
|
||||
~~~~~~~~~~~~
|
||||
|
||||
To return to the original head after a bisect session, you issue the
|
||||
To return to the original head after a bisect session, issue the
|
||||
following command:
|
||||
|
||||
------------------------------------------------
|
||||
@@ -95,8 +95,8 @@ the bisection state).
|
||||
Bisect visualize
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
To see the currently remaining suspects in 'gitk', the following command
|
||||
is issued during the bisection process:
|
||||
To see the currently remaining suspects in 'gitk', issue the following
|
||||
command during the bisection process:
|
||||
|
||||
------------
|
||||
$ git bisect visualize
|
||||
@@ -115,7 +115,7 @@ $ git bisect view --stat
|
||||
Bisect log and bisect replay
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After having marked revisions as good or bad, you issue the following
|
||||
After having marked revisions as good or bad, issue the following
|
||||
command to show what has been done so far:
|
||||
|
||||
------------
|
||||
@@ -135,7 +135,7 @@ $ git bisect replay that-file
|
||||
Avoiding testing a commit
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If in the middle of a bisect session, you know that the next suggested
|
||||
If, in the middle of a bisect session, you know that the next suggested
|
||||
revision is not a good one to test (e.g. the change the commit
|
||||
introduces is known not to work in your environment and you know it
|
||||
does not have anything to do with the bug you are chasing), you may
|
||||
@@ -151,8 +151,8 @@ $ git reset --hard HEAD~3 # try 3 revisions before what
|
||||
# was suggested
|
||||
------------
|
||||
|
||||
Then compile and test the chosen revision. Afterwards the revision
|
||||
is marked as good or bad in the usual manner.
|
||||
Then compile and test the chosen revision, and afterwards mark
|
||||
the revision as good or bad in the usual manner.
|
||||
|
||||
Bisect skip
|
||||
~~~~~~~~~~~~
|
||||
@@ -175,8 +175,8 @@ using the "'<commit1>'..'<commit2>'" notation. For example:
|
||||
$ git bisect skip v2.5..v2.6
|
||||
------------
|
||||
|
||||
The effect of this would be that no commit between `v2.5` excluded and
|
||||
`v2.6` included could be tested.
|
||||
This tells the bisect process that no commit after `v2.5`, up to and
|
||||
including `v2.6`, should be tested.
|
||||
|
||||
Note that if you also want to skip the first commit of the range you
|
||||
would issue the command:
|
||||
@@ -185,8 +185,8 @@ would issue the command:
|
||||
$ git bisect skip v2.5 v2.5..v2.6
|
||||
------------
|
||||
|
||||
This would cause the commits between `v2.5` included and `v2.6` included
|
||||
to be skipped.
|
||||
This tells the bisect process that the commits between `v2.5` included
|
||||
and `v2.6` included should be skipped.
|
||||
|
||||
|
||||
Cutting down bisection by giving more parameters to bisect start
|
||||
|
||||
@@ -19,13 +19,13 @@ DESCRIPTION
|
||||
|
||||
Some workflows require that one or more branches of development on one
|
||||
machine be replicated on another machine, but the two machines cannot
|
||||
be directly connected so the interactive git protocols (git, ssh,
|
||||
rsync, http) cannot be used. This command provides support for
|
||||
be directly connected, and therefore the interactive git protocols (git,
|
||||
ssh, rsync, http) cannot be used. This command provides support for
|
||||
'git-fetch' and 'git-pull' to operate by packaging objects and references
|
||||
in an archive at the originating machine, then importing those into
|
||||
another repository using 'git-fetch' and 'git-pull'
|
||||
after moving the archive by some means (i.e., by sneakernet). As no
|
||||
direct connection between repositories exists, the user must specify a
|
||||
direct connection between the repositories exists, the user must specify a
|
||||
basis for the bundle that is held by the destination repository: the
|
||||
bundle assumes that all objects in the basis are already in the
|
||||
destination repository.
|
||||
@@ -43,7 +43,7 @@ verify <file>::
|
||||
bundle format itself as well as checking that the prerequisite
|
||||
commits exist and are fully linked in the current repository.
|
||||
'git-bundle' prints a list of missing commits, if any, and exits
|
||||
with non-zero status.
|
||||
with a non-zero status.
|
||||
|
||||
list-heads <file>::
|
||||
Lists the references defined in the bundle. If followed by a
|
||||
@@ -53,14 +53,14 @@ list-heads <file>::
|
||||
unbundle <file>::
|
||||
Passes the objects in the bundle to 'git-index-pack'
|
||||
for storage in the repository, then prints the names of all
|
||||
defined references. If a reflist is given, only references
|
||||
matching those in the given list are printed. This command is
|
||||
defined references. If a list of references is given, only
|
||||
references matching those in the list are printed. This command is
|
||||
really plumbing, intended to be called only by 'git-fetch'.
|
||||
|
||||
[git-rev-list-args...]::
|
||||
A list of arguments, acceptable to 'git-rev-parse' and
|
||||
'git-rev-list', that specify the specific objects and references
|
||||
to transport. For example, "master~10..master" causes the
|
||||
'git-rev-list', that specifies the specific objects and references
|
||||
to transport. For example, `master\~10..master` causes the
|
||||
current master reference to be packaged along with all objects
|
||||
added since its 10th ancestor commit. There is no explicit
|
||||
limit to the number of references and objects that may be
|
||||
@@ -71,24 +71,24 @@ unbundle <file>::
|
||||
A list of references used to limit the references reported as
|
||||
available. This is principally of use to 'git-fetch', which
|
||||
expects to receive only those references asked for and not
|
||||
necessarily everything in the pack (in this case, 'git-bundle' is
|
||||
acting like 'git-fetch-pack').
|
||||
necessarily everything in the pack (in this case, 'git-bundle' acts
|
||||
like 'git-fetch-pack').
|
||||
|
||||
SPECIFYING REFERENCES
|
||||
---------------------
|
||||
|
||||
'git-bundle' will only package references that are shown by
|
||||
'git-show-ref': this includes heads, tags, and remote heads. References
|
||||
such as master~1 cannot be packaged, but are perfectly suitable for
|
||||
such as `master\~1` cannot be packaged, but are perfectly suitable for
|
||||
defining the basis. More than one reference may be packaged, and more
|
||||
than one basis can be specified. The objects packaged are those not
|
||||
contained in the union of the given bases. Each basis can be
|
||||
specified explicitly (e.g., ^master~10), or implicitly (e.g.,
|
||||
master~10..master, --since=10.days.ago master).
|
||||
specified explicitly (e.g. `^master\~10`), or implicitly (e.g.
|
||||
`master\~10..master`, `--since=10.days.ago master`).
|
||||
|
||||
It is very important that the basis used be held by the destination.
|
||||
It is okay to err on the side of conservatism, causing the bundle file
|
||||
to contain objects already in the destination as these are ignored
|
||||
It is okay to err on the side of caution, causing the bundle file
|
||||
to contain objects already in the destination, as these are ignored
|
||||
when unpacking at the destination.
|
||||
|
||||
EXAMPLE
|
||||
@@ -97,13 +97,13 @@ EXAMPLE
|
||||
Assume you want to transfer the history from a repository R1 on machine A
|
||||
to another repository R2 on machine B.
|
||||
For whatever reason, direct connection between A and B is not allowed,
|
||||
but we can move data from A to B via some mechanism (CD, email, etc).
|
||||
We want to update R2 with developments made on branch master in R1.
|
||||
but we can move data from A to B via some mechanism (CD, email, etc.).
|
||||
We want to update R2 with development made on the branch master in R1.
|
||||
|
||||
To bootstrap the process, you can first create a bundle that doesn't have
|
||||
any basis. You can use a tag to remember up to what commit you sent out
|
||||
in order to make it easy to later update the other repository with
|
||||
incremental bundle,
|
||||
To bootstrap the process, you can first create a bundle that does not have
|
||||
any basis. You can use a tag to remember up to what commit you last
|
||||
processed, in order to make it easy to later update the other repository
|
||||
with an incremental bundle:
|
||||
|
||||
----------------
|
||||
machineA$ cd R1
|
||||
@@ -111,17 +111,17 @@ machineA$ git bundle create file.bundle master
|
||||
machineA$ git tag -f lastR2bundle master
|
||||
----------------
|
||||
|
||||
Then you sneakernet file.bundle to the target machine B. Because you don't
|
||||
have to have any object to extract objects from such a bundle, not only
|
||||
you can fetch/pull from a bundle, you can clone from it as if it was a
|
||||
remote repository.
|
||||
Then you transfer file.bundle to the target machine B. If you are creating
|
||||
the repository on machine B, then you can clone from the bundle as if it
|
||||
were a remote repository instead of creating an empty repository and then
|
||||
pulling or fetching objects from the bundle:
|
||||
|
||||
----------------
|
||||
machineB$ git clone /home/me/tmp/file.bundle R2
|
||||
----------------
|
||||
|
||||
This will define a remote called "origin" in the resulting repository that
|
||||
lets you fetch and pull from the bundle. $GIT_DIR/config file in R2 may
|
||||
lets you fetch and pull from the bundle. The $GIT_DIR/config file in R2 will
|
||||
have an entry like this:
|
||||
|
||||
------------------------
|
||||
@@ -130,12 +130,12 @@ have an entry like this:
|
||||
fetch = refs/heads/*:refs/remotes/origin/*
|
||||
------------------------
|
||||
|
||||
You can fetch/pull to update the resulting mine.git repository after
|
||||
replacing the bundle you store at /home/me/tmp/file.bundle with incremental
|
||||
updates from here on.
|
||||
To update the resulting mine.git repository, you can fetch or pull after
|
||||
replacing the bundle stored at /home/me/tmp/file.bundle with incremental
|
||||
updates.
|
||||
|
||||
After working more in the original repository, you can create an
|
||||
incremental bundle to update the other:
|
||||
After working some more in the original repository, you can create an
|
||||
incremental bundle to update the other repository:
|
||||
|
||||
----------------
|
||||
machineA$ cd R1
|
||||
@@ -143,8 +143,8 @@ machineA$ git bundle create file.bundle lastR2bundle..master
|
||||
machineA$ git tag -f lastR2bundle master
|
||||
----------------
|
||||
|
||||
and sneakernet it to the other machine to replace /home/me/tmp/file.bundle,
|
||||
and pull from it.
|
||||
You then transfer the bundle to the other machine to replace
|
||||
/home/me/tmp/file.bundle, and pull from it.
|
||||
|
||||
----------------
|
||||
machineB$ cd R2
|
||||
@@ -152,49 +152,49 @@ machineB$ git pull
|
||||
----------------
|
||||
|
||||
If you know up to what commit the intended recipient repository should
|
||||
have the necessary objects for, you can use that knowledge to specify the
|
||||
have the necessary objects, you can use that knowledge to specify the
|
||||
basis, giving a cut-off point to limit the revisions and objects that go
|
||||
in the resulting bundle. The previous example used lastR2bundle tag
|
||||
for this purpose, but you can use other options you would give to
|
||||
for this purpose, but you can use any other options that you would give to
|
||||
the linkgit:git-log[1] command. Here are more examples:
|
||||
|
||||
You can use a tag that is present in both.
|
||||
You can use a tag that is present in both:
|
||||
|
||||
----------------
|
||||
$ git bundle create mybundle v1.0.0..master
|
||||
----------------
|
||||
|
||||
You can use a basis based on time.
|
||||
You can use a basis based on time:
|
||||
|
||||
----------------
|
||||
$ git bundle create mybundle --since=10.days master
|
||||
----------------
|
||||
|
||||
Or you can use the number of commits.
|
||||
You can use the number of commits:
|
||||
|
||||
----------------
|
||||
$ git bundle create mybundle -10 master
|
||||
----------------
|
||||
|
||||
You can run `git-bundle verify` to see if you can extract from a bundle
|
||||
that was created with a basis.
|
||||
that was created with a basis:
|
||||
|
||||
----------------
|
||||
$ git bundle verify mybundle
|
||||
----------------
|
||||
|
||||
This will list what commits you must have in order to extract from the
|
||||
bundle and will error out if you don't have them.
|
||||
bundle and will error out if you do not have them.
|
||||
|
||||
A bundle from a recipient repository's point of view is just like a
|
||||
regular repository it fetches/pulls from. You can for example map
|
||||
refs, like this example, when fetching:
|
||||
regular repository which it fetches or pulls from. You can, for example, map
|
||||
references when fetching:
|
||||
|
||||
----------------
|
||||
$ git fetch mybundle master:localRef
|
||||
----------------
|
||||
|
||||
Or see what refs it offers.
|
||||
You can also see what references it offers.
|
||||
|
||||
----------------
|
||||
$ git ls-remote mybundle
|
||||
|
||||
@@ -3,7 +3,7 @@ git-cat-file(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-cat-file - Provide content or type/size information for repository objects
|
||||
git-cat-file - Provide content or type and size information for repository objects
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@@ -14,19 +14,19 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
In the first form, provides content or type of objects in the repository. The
|
||||
type is required unless '-t' or '-p' is used to find the object type, or '-s'
|
||||
is used to find the object size.
|
||||
In its first form, the command provides the content or the type of an object in
|
||||
the repository. The type is required unless '-t' or '-p' is used to find the
|
||||
object type, or '-s' is used to find the object size.
|
||||
|
||||
In the second form, a list of object (separated by LFs) is provided on stdin,
|
||||
and the SHA1, type, and size of each object is printed on stdout.
|
||||
In the second form, a list of objects (separated by linefeeds) is provided on
|
||||
stdin, and the SHA1, type, and size of each object is printed on stdout.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<object>::
|
||||
The name of the object to show.
|
||||
For a more complete list of ways to spell object names, see
|
||||
"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
||||
the "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
|
||||
|
||||
-t::
|
||||
Instead of the content, show the object type identified by
|
||||
@@ -56,8 +56,8 @@ OPTIONS
|
||||
stdin. May not be combined with any other options or arguments.
|
||||
|
||||
--batch-check::
|
||||
Print the SHA1, type, and size of each object provided on stdin. May not be
|
||||
combined with any other options or arguments.
|
||||
Print the SHA1, type, and size of each object provided on stdin. May not
|
||||
be combined with any other options or arguments.
|
||||
|
||||
OUTPUT
|
||||
------
|
||||
|
||||
@@ -14,7 +14,7 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
For every pathname, this command will list if each attr is 'unspecified',
|
||||
For every pathname, this command will list if each attribute is 'unspecified',
|
||||
'set', or 'unset' as a gitattribute on that pathname.
|
||||
|
||||
OPTIONS
|
||||
@@ -23,11 +23,11 @@ OPTIONS
|
||||
Read file names from stdin instead of from the command-line.
|
||||
|
||||
-z::
|
||||
Only meaningful with `--stdin`; paths are separated with
|
||||
NUL character instead of LF.
|
||||
Only meaningful with `--stdin`; paths are separated with a
|
||||
NUL character instead of a linefeed character.
|
||||
|
||||
\--::
|
||||
Interpret all preceding arguments as attributes, and all following
|
||||
Interpret all preceding arguments as attributes and all following
|
||||
arguments as path names. If not supplied, only the first argument will
|
||||
be treated as an attribute.
|
||||
|
||||
@@ -37,12 +37,12 @@ OUTPUT
|
||||
The output is of the form:
|
||||
<path> COLON SP <attribute> COLON SP <info> LF
|
||||
|
||||
Where <path> is the path of a file being queried, <attribute> is an attribute
|
||||
<path> is the path of a file being queried, <attribute> is an attribute
|
||||
being queried and <info> can be either:
|
||||
|
||||
'unspecified';; when the attribute is not defined for the path.
|
||||
'unset';; when the attribute is defined to false.
|
||||
'set';; when the attribute is defined to true.
|
||||
'unset';; when the attribute is defined as false.
|
||||
'set';; when the attribute is defined as true.
|
||||
<value>;; when a value has been assigned to the attribute.
|
||||
|
||||
EXAMPLES
|
||||
@@ -69,7 +69,7 @@ org/example/MyClass.java: diff: java
|
||||
org/example/MyClass.java: myAttr: set
|
||||
---------------
|
||||
|
||||
* Listing attribute for multiple files:
|
||||
* Listing an attribute for multiple files:
|
||||
---------------
|
||||
$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
|
||||
org/example/MyClass.java: myAttr: set
|
||||
|
||||
@@ -3,7 +3,7 @@ git-check-ref-format(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-check-ref-format - Make sure ref name is well formed
|
||||
git-check-ref-format - Ensures that a reference name is well formed
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
@@ -11,40 +11,40 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Checks if a given 'refname' is acceptable, and exits non-zero if
|
||||
it is not.
|
||||
Checks if a given 'refname' is acceptable, and exits with a non-zero
|
||||
status if it is not.
|
||||
|
||||
A reference is used in git to specify branches and tags. A
|
||||
branch head is stored under `$GIT_DIR/refs/heads` directory, and
|
||||
a tag is stored under `$GIT_DIR/refs/tags` directory. git
|
||||
imposes the following rules on how refs are named:
|
||||
branch head is stored under the `$GIT_DIR/refs/heads` directory, and
|
||||
a tag is stored under the `$GIT_DIR/refs/tags` directory. git
|
||||
imposes the following rules on how references are named:
|
||||
|
||||
. It can include slash `/` for hierarchical (directory)
|
||||
. They can include slash `/` for hierarchical (directory)
|
||||
grouping, but no slash-separated component can begin with a
|
||||
dot `.`;
|
||||
dot `.`.
|
||||
|
||||
. It cannot have two consecutive dots `..` anywhere;
|
||||
. They cannot have two consecutive dots `..` anywhere.
|
||||
|
||||
. It cannot have ASCII control character (i.e. bytes whose
|
||||
. They cannot have ASCII control characters (i.e. bytes whose
|
||||
values are lower than \040, or \177 `DEL`), space, tilde `~`,
|
||||
caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
|
||||
or open bracket `[` anywhere;
|
||||
or open bracket `[` anywhere.
|
||||
|
||||
. It cannot end with a slash `/`.
|
||||
. They cannot end with a slash `/`.
|
||||
|
||||
These rules makes it easy for shell script based tools to parse
|
||||
refnames, pathname expansion by the shell when a refname is used
|
||||
These rules make it easy for shell script based tools to parse
|
||||
reference names, pathname expansion by the shell when a reference name is used
|
||||
unquoted (by mistake), and also avoids ambiguities in certain
|
||||
refname expressions (see linkgit:git-rev-parse[1]). Namely:
|
||||
reference name expressions (see linkgit:git-rev-parse[1]):
|
||||
|
||||
. double-dot `..` are often used as in `ref1..ref2`, and in some
|
||||
context this notation means `{caret}ref1 ref2` (i.e. not in
|
||||
ref1 and in ref2).
|
||||
. A double-dot `..` is often used as in `ref1..ref2`, and in some
|
||||
contexts this notation means `{caret}ref1 ref2` (i.e. not in
|
||||
`ref1` and in `ref2`).
|
||||
|
||||
. tilde `~` and caret `{caret}` are used to introduce postfix
|
||||
. A tilde `~` and caret `{caret}` are used to introduce the postfix
|
||||
'nth parent' and 'peel onion' operation.
|
||||
|
||||
. colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
|
||||
. A colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
|
||||
value and store it in dstref" in fetch and push operations.
|
||||
It may also be used to select a specific object such as with
|
||||
'git-cat-file': "git cat-file blob v1.3.3:refs.c".
|
||||
|
||||
@@ -24,6 +24,9 @@ repository, or incrementally import into an existing one.
|
||||
Splitting the CVS log into patch sets is done by 'cvsps'.
|
||||
At least version 2.1 is required.
|
||||
|
||||
*WARNING:* for certain situations the import leads to incorrect results.
|
||||
Please see the section <<issues,ISSUES>> for further reference.
|
||||
|
||||
You should *never* do any work of your own on the branches that are
|
||||
created by 'git-cvsimport'. By default initial import will create and populate a
|
||||
"master" branch from the CVS repository's main branch which you're free
|
||||
@@ -62,7 +65,7 @@ OPTIONS
|
||||
-r <remote>::
|
||||
The git remote to import this CVS repository into.
|
||||
Moves all CVS branches into remotes/<remote>/<branch>
|
||||
akin to the 'git-clone' "--use-separate-remote" option.
|
||||
akin to the way 'git-clone' uses 'origin' by default.
|
||||
|
||||
-o <branch-for-HEAD>::
|
||||
When no remote is specified (via -r) the 'HEAD' branch
|
||||
@@ -164,6 +167,37 @@ If '-v' is specified, the script reports what it is doing.
|
||||
Otherwise, success is indicated the Unix way, i.e. by simply exiting with
|
||||
a zero exit status.
|
||||
|
||||
[[issues]]
|
||||
ISSUES
|
||||
------
|
||||
Problems related to timestamps:
|
||||
|
||||
* If timestamps of commits in the cvs repository are not stable enough
|
||||
to be used for ordering commits
|
||||
* If any files were ever "cvs import"ed more than once (e.g., import of
|
||||
more than one vendor release)
|
||||
* If the timestamp order of different files cross the revision order
|
||||
within the commit matching time window
|
||||
|
||||
Problems related to branches:
|
||||
|
||||
* Branches on which no commits have been made are not imported
|
||||
* All files from the branching point are added to a branch even if
|
||||
never added in cvs
|
||||
* files added to the source branch *after* a daughter branch was
|
||||
created: If previously no commit was made on the daugther branch they
|
||||
will erroneously be added to the daughter branch in git
|
||||
|
||||
Problems related to tags:
|
||||
|
||||
* Multiple tags on the same revision are not imported
|
||||
|
||||
If you suspect that any of these issues may apply to the repository you
|
||||
want to import consider using these alternative tools which proved to be
|
||||
more stable in practise:
|
||||
|
||||
* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
|
||||
* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
@@ -40,8 +40,8 @@ include::merge-options.txt[]
|
||||
include::merge-strategies.txt[]
|
||||
|
||||
|
||||
If you tried a merge which resulted in a complex conflicts and
|
||||
would want to start over, you can recover with 'git-reset'.
|
||||
If you tried a merge which resulted in complex conflicts and
|
||||
want to start over, you can recover with 'git-reset'.
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
@@ -20,7 +20,7 @@ IOW, you can use this thing to look for likely duplicate commits.
|
||||
|
||||
When dealing with 'git-diff-tree' output, it takes advantage of
|
||||
the fact that the patch is prefixed with the object name of the
|
||||
commit, and outputs two 40-byte hexadecimal string. The first
|
||||
commit, and outputs two 40-byte hexadecimal strings. The first
|
||||
string is the patch ID, and the second string is the commit ID.
|
||||
This can be used to make a mapping from patch ID to commit ID.
|
||||
|
||||
|
||||
@@ -151,6 +151,10 @@ indicating whether the checkout was a branch checkout (changing branches,
|
||||
flag=1) or a file checkout (retrieving a file from the index, flag=0).
|
||||
This hook cannot affect the outcome of 'git-checkout'.
|
||||
|
||||
It is also run after 'git-clone', unless the --no-checkout (-n) option is
|
||||
used. The first parameter given to the hook is the null-ref, the second the
|
||||
ref of the new HEAD and the flag is always 1.
|
||||
|
||||
This hook can be used to perform repository validity checks, auto-display
|
||||
differences from the previous HEAD if different, or set working dir metadata
|
||||
properties.
|
||||
|
||||
@@ -3,15 +3,15 @@ MERGE STRATEGIES
|
||||
|
||||
resolve::
|
||||
This can only resolve two heads (i.e. the current branch
|
||||
and another branch you pulled from) using 3-way merge
|
||||
and another branch you pulled from) using a 3-way merge
|
||||
algorithm. It tries to carefully detect criss-cross
|
||||
merge ambiguities and is considered generally safe and
|
||||
fast.
|
||||
|
||||
recursive::
|
||||
This can only resolve two heads using 3-way merge
|
||||
algorithm. When there are more than one common
|
||||
ancestors that can be used for 3-way merge, it creates a
|
||||
This can only resolve two heads using a 3-way merge
|
||||
algorithm. When there is more than one common
|
||||
ancestor that can be used for 3-way merge, it creates a
|
||||
merged tree of the common ancestors and uses that as
|
||||
the reference tree for the 3-way merge. This has been
|
||||
reported to result in fewer merge conflicts without
|
||||
@@ -22,11 +22,11 @@ recursive::
|
||||
pulling or merging one branch.
|
||||
|
||||
octopus::
|
||||
This resolves more than two-head case, but refuses to do
|
||||
complex merge that needs manual resolution. It is
|
||||
This resolves cases with more than two heads, but refuses to do
|
||||
a complex merge that needs manual resolution. It is
|
||||
primarily meant to be used for bundling topic branch
|
||||
heads together. This is the default merge strategy when
|
||||
pulling or merging more than one branches.
|
||||
pulling or merging more than one branch.
|
||||
|
||||
ours::
|
||||
This resolves any number of heads, but the result of the
|
||||
|
||||
13
Makefile
13
Makefile
@@ -264,6 +264,18 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
|
||||
BASIC_CFLAGS =
|
||||
BASIC_LDFLAGS =
|
||||
|
||||
# Guard against environment variables
|
||||
BUILTIN_OBJS =
|
||||
BUILT_INS =
|
||||
COMPAT_CFLAGS =
|
||||
COMPAT_OBJS =
|
||||
LIB_H =
|
||||
LIB_OBJS =
|
||||
PROGRAMS =
|
||||
SCRIPT_PERL =
|
||||
SCRIPT_SH =
|
||||
TEST_PROGRAMS =
|
||||
|
||||
SCRIPT_SH += git-am.sh
|
||||
SCRIPT_SH += git-bisect.sh
|
||||
SCRIPT_SH += git-filter-branch.sh
|
||||
@@ -714,6 +726,7 @@ ifeq ($(uname_S),FreeBSD)
|
||||
BASIC_CFLAGS += -I/usr/local/include
|
||||
BASIC_LDFLAGS += -L/usr/local/lib
|
||||
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
|
||||
USE_ST_TIMESPEC = YesPlease
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
|
||||
PTHREAD_LIBS = -pthread
|
||||
|
||||
73
attr.c
73
attr.c
@@ -1,3 +1,4 @@
|
||||
#define NO_THE_INDEX_COMPATIBILITY_MACROS
|
||||
#include "cache.h"
|
||||
#include "attr.h"
|
||||
|
||||
@@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
|
||||
return res;
|
||||
}
|
||||
|
||||
static enum git_attr_direction direction;
|
||||
static struct index_state *use_index;
|
||||
|
||||
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
|
||||
{
|
||||
FILE *fp = fopen(path, "r");
|
||||
@@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
|
||||
unsigned long sz;
|
||||
enum object_type type;
|
||||
void *data;
|
||||
struct index_state *istate = use_index ? use_index : &the_index;
|
||||
|
||||
len = strlen(path);
|
||||
pos = cache_name_pos(path, len);
|
||||
pos = index_name_pos(istate, path, len);
|
||||
if (pos < 0) {
|
||||
/*
|
||||
* We might be in the middle of a merge, in which
|
||||
@@ -350,15 +355,15 @@ static void *read_index_data(const char *path)
|
||||
*/
|
||||
int i;
|
||||
for (i = -pos - 1;
|
||||
(pos < 0 && i < active_nr &&
|
||||
!strcmp(active_cache[i]->name, path));
|
||||
(pos < 0 && i < istate->cache_nr &&
|
||||
!strcmp(istate->cache[i]->name, path));
|
||||
i++)
|
||||
if (ce_stage(active_cache[i]) == 2)
|
||||
if (ce_stage(istate->cache[i]) == 2)
|
||||
pos = i;
|
||||
}
|
||||
if (pos < 0)
|
||||
return NULL;
|
||||
data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
|
||||
data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
|
||||
if (!data || type != OBJ_BLOB) {
|
||||
free(data);
|
||||
return NULL;
|
||||
@@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
|
||||
return data;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
|
||||
{
|
||||
struct attr_stack *res;
|
||||
char *buf, *sp;
|
||||
int lineno = 0;
|
||||
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
|
||||
/*
|
||||
* There is no checked out .gitattributes file there, but
|
||||
* we might have it in the index. We allow operation in a
|
||||
* sparsely checked out work tree, so read from it.
|
||||
*/
|
||||
buf = read_index_data(path);
|
||||
if (!buf)
|
||||
return res;
|
||||
return NULL;
|
||||
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
for (sp = buf; *sp; ) {
|
||||
char *ep;
|
||||
int more;
|
||||
@@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
{
|
||||
struct attr_stack *res;
|
||||
|
||||
if (direction == GIT_ATTR_CHECKOUT) {
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
if (!res)
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
}
|
||||
else {
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
if (!res)
|
||||
/*
|
||||
* There is no checked out .gitattributes file there, but
|
||||
* we might have it in the index. We allow operation in a
|
||||
* sparsely checked out work tree, so read from it.
|
||||
*/
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
}
|
||||
if (!res)
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
return res;
|
||||
}
|
||||
|
||||
#if DEBUG_ATTR
|
||||
static void debug_info(const char *what, struct attr_stack *elem)
|
||||
{
|
||||
@@ -428,6 +447,15 @@ static void debug_set(const char *what, const char *match, struct git_attr *attr
|
||||
#define debug_set(a,b,c,d) do { ; } while (0)
|
||||
#endif
|
||||
|
||||
static void drop_attr_stack(void)
|
||||
{
|
||||
while (attr_stack) {
|
||||
struct attr_stack *elem = attr_stack;
|
||||
attr_stack = elem->prev;
|
||||
free_attr_elem(elem);
|
||||
}
|
||||
}
|
||||
|
||||
static void bootstrap_attr_stack(void)
|
||||
{
|
||||
if (!attr_stack) {
|
||||
@@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
|
||||
{
|
||||
enum git_attr_direction old = direction;
|
||||
direction = new;
|
||||
if (new != old)
|
||||
drop_attr_stack();
|
||||
use_index = istate;
|
||||
}
|
||||
|
||||
6
attr.h
6
attr.h
@@ -31,4 +31,10 @@ struct git_attr_check {
|
||||
|
||||
int git_checkattr(const char *path, int, struct git_attr_check *);
|
||||
|
||||
enum git_attr_direction {
|
||||
GIT_ATTR_CHECKIN,
|
||||
GIT_ATTR_CHECKOUT
|
||||
};
|
||||
void git_attr_set_direction(enum git_attr_direction, struct index_state *);
|
||||
|
||||
#endif /* ATTR_H */
|
||||
|
||||
@@ -2451,7 +2451,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
|
||||
if ((st_mode ^ patch->old_mode) & S_IFMT)
|
||||
return error("%s: wrong type", old_name);
|
||||
if (st_mode != patch->old_mode)
|
||||
fprintf(stderr, "warning: %s has type %o, expected %o\n",
|
||||
warning("%s has type %o, expected %o",
|
||||
old_name, st_mode, patch->old_mode);
|
||||
if (!patch->new_mode && !patch->is_delete)
|
||||
patch->new_mode = st_mode;
|
||||
@@ -2932,8 +2932,7 @@ static int write_out_one_reject(struct patch *patch)
|
||||
cnt = strlen(patch->new_name);
|
||||
if (ARRAY_SIZE(namebuf) <= cnt + 5) {
|
||||
cnt = ARRAY_SIZE(namebuf) - 5;
|
||||
fprintf(stderr,
|
||||
"warning: truncating .rej filename to %.*s.rej",
|
||||
warning("truncating .rej filename to %.*s.rej",
|
||||
cnt - 1, patch->new_name);
|
||||
}
|
||||
memcpy(namebuf, patch->new_name, cnt);
|
||||
@@ -3315,8 +3314,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
squelch_whitespace_errors < whitespace_error) {
|
||||
int squelched =
|
||||
whitespace_error - squelch_whitespace_errors;
|
||||
fprintf(stderr, "warning: squelched %d "
|
||||
"whitespace error%s\n",
|
||||
warning("squelched %d "
|
||||
"whitespace error%s",
|
||||
squelched,
|
||||
squelched == 1 ? "" : "s");
|
||||
}
|
||||
@@ -3326,12 +3325,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
whitespace_error == 1 ? "" : "s",
|
||||
whitespace_error == 1 ? "s" : "");
|
||||
if (applied_after_fixing_ws && apply)
|
||||
fprintf(stderr, "warning: %d line%s applied after"
|
||||
" fixing whitespace errors.\n",
|
||||
warning("%d line%s applied after"
|
||||
" fixing whitespace errors.",
|
||||
applied_after_fixing_ws,
|
||||
applied_after_fixing_ws == 1 ? "" : "s");
|
||||
else if (whitespace_error)
|
||||
fprintf(stderr, "warning: %d line%s add%s whitespace errors.\n",
|
||||
warning("%d line%s add%s whitespace errors.",
|
||||
whitespace_error,
|
||||
whitespace_error == 1 ? "" : "s",
|
||||
whitespace_error == 1 ? "s" : "");
|
||||
|
||||
@@ -2250,6 +2250,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||
parse_done:
|
||||
argc = parse_options_end(&ctx);
|
||||
|
||||
if (revs_file && read_ancestry(revs_file))
|
||||
die("reading graft file %s failed: %s",
|
||||
revs_file, strerror(errno));
|
||||
|
||||
if (cmd_is_annotate) {
|
||||
output_option |= OUTPUT_ANNOTATE_COMPAT;
|
||||
blame_date_mode = DATE_ISO8601;
|
||||
@@ -2418,10 +2422,6 @@ parse_done:
|
||||
sb.ent = ent;
|
||||
sb.path = path;
|
||||
|
||||
if (revs_file && read_ancestry(revs_file))
|
||||
die("reading graft file %s failed: %s",
|
||||
revs_file, strerror(errno));
|
||||
|
||||
read_mailmap(&mailmap, NULL);
|
||||
|
||||
if (!incremental)
|
||||
|
||||
@@ -171,7 +171,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
ret = 1;
|
||||
} else {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
printf("Deleted %sbranch %s (%s).\n", remote,
|
||||
printf("Deleted %sbranch %s (was %s).\n", remote,
|
||||
bname.buf,
|
||||
find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||
strbuf_addf(&buf, "branch.%s", bname.buf);
|
||||
|
||||
@@ -558,8 +558,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
|
||||
|
||||
if (!old.commit && !opts->force) {
|
||||
if (!opts->quiet) {
|
||||
fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
|
||||
fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
|
||||
warning("You appear to be on a branch yet to be born.");
|
||||
warning("Forcing checkout of %s.", new->name);
|
||||
}
|
||||
opts->force = 1;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
||||
if (message)
|
||||
message += 2;
|
||||
|
||||
if (commit->parents) {
|
||||
if (commit->parents &&
|
||||
get_object_mark(&commit->parents->item->object) != 0) {
|
||||
parse_commit(commit->parents->item);
|
||||
diff_tree_sha1(commit->parents->item->tree->object.sha1,
|
||||
commit->tree->object.sha1, "", &rev->diffopt);
|
||||
|
||||
@@ -605,7 +605,7 @@ static struct ref *do_fetch_pack(int fd[2],
|
||||
/* When cloning, it is not unusual to have
|
||||
* no common commit.
|
||||
*/
|
||||
fprintf(stderr, "warning: no common commits\n");
|
||||
warning("no common commits");
|
||||
|
||||
if (get_pack(fd, pack_lockfile))
|
||||
die("git fetch-pack: fetch failed.");
|
||||
|
||||
@@ -197,11 +197,7 @@ static int update_local_ref(struct ref *ref,
|
||||
struct commit *current = NULL, *updated;
|
||||
enum object_type type;
|
||||
struct branch *current_branch = branch_get(NULL);
|
||||
const char *pretty_ref = ref->name + (
|
||||
!prefixcmp(ref->name, "refs/heads/") ? 11 :
|
||||
!prefixcmp(ref->name, "refs/tags/") ? 10 :
|
||||
!prefixcmp(ref->name, "refs/remotes/") ? 13 :
|
||||
0);
|
||||
const char *pretty_ref = prettify_ref(ref);
|
||||
|
||||
*display = 0;
|
||||
type = sha1_object_info(ref->new_sha1, NULL);
|
||||
@@ -544,7 +540,8 @@ static void check_not_current_branch(struct ref *ref_map)
|
||||
for (; ref_map; ref_map = ref_map->next)
|
||||
if (ref_map->peer_ref && !strcmp(current_branch->refname,
|
||||
ref_map->peer_ref->name))
|
||||
die("Refusing to fetch into current branch");
|
||||
die("Refusing to fetch into current branch %s "
|
||||
"of non-bare repository", current_branch->refname);
|
||||
}
|
||||
|
||||
static int do_fetch(struct transport *transport,
|
||||
|
||||
@@ -130,8 +130,7 @@ static void copy_templates(const char *template_dir)
|
||||
}
|
||||
dir = opendir(template_path);
|
||||
if (!dir) {
|
||||
fprintf(stderr, "warning: templates not found %s\n",
|
||||
template_dir);
|
||||
warning("templates not found %s", template_dir);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,8 +143,8 @@ static void copy_templates(const char *template_dir)
|
||||
|
||||
if (repository_format_version &&
|
||||
repository_format_version != GIT_REPO_VERSION) {
|
||||
fprintf(stderr, "warning: not copying templates of "
|
||||
"a wrong format version %d from '%s'\n",
|
||||
warning("not copying templates of "
|
||||
"a wrong format version %d from '%s'",
|
||||
repository_format_version,
|
||||
template_dir);
|
||||
closedir(dir);
|
||||
|
||||
@@ -1293,7 +1293,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
|
||||
max_size = trg_entry->delta_size;
|
||||
ref_depth = trg->depth;
|
||||
}
|
||||
max_size = max_size * (max_depth - src->depth) /
|
||||
max_size = (uint64_t)max_size * (max_depth - src->depth) /
|
||||
(max_depth - ref_depth + 1);
|
||||
if (max_size == 0)
|
||||
return 0;
|
||||
|
||||
@@ -48,6 +48,71 @@ static void set_refspecs(const char **refs, int nr)
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_push_tracking(void)
|
||||
{
|
||||
struct strbuf refspec = STRBUF_INIT;
|
||||
struct branch *branch = branch_get(NULL);
|
||||
if (!branch)
|
||||
die("You are not currently on a branch.");
|
||||
if (!branch->merge_nr)
|
||||
die("The current branch %s is not tracking anything.",
|
||||
branch->name);
|
||||
if (branch->merge_nr != 1)
|
||||
die("The current branch %s is tracking multiple branches, "
|
||||
"refusing to push.", branch->name);
|
||||
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
|
||||
add_refspec(refspec.buf);
|
||||
}
|
||||
|
||||
static const char *warn_unconfigured_push_msg[] = {
|
||||
"You did not specify any refspecs to push, and the current remote",
|
||||
"has not configured any push refspecs. The default action in this",
|
||||
"case is to push all matching refspecs, that is, all branches",
|
||||
"that exist both locally and remotely will be updated. This may",
|
||||
"not necessarily be what you want to happen.",
|
||||
"",
|
||||
"You can specify what action you want to take in this case, and",
|
||||
"avoid seeing this message again, by configuring 'push.default' to:",
|
||||
" 'nothing' : Do not push anything",
|
||||
" 'matching' : Push all matching branches (default)",
|
||||
" 'tracking' : Push the current branch to whatever it is tracking",
|
||||
" 'current' : Push the current branch"
|
||||
};
|
||||
|
||||
static void warn_unconfigured_push(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++)
|
||||
warning("%s", warn_unconfigured_push_msg[i]);
|
||||
}
|
||||
|
||||
static void setup_default_push_refspecs(void)
|
||||
{
|
||||
git_config(git_default_config, NULL);
|
||||
switch (push_default) {
|
||||
case PUSH_DEFAULT_UNSPECIFIED:
|
||||
warn_unconfigured_push();
|
||||
/* fallthrough */
|
||||
|
||||
case PUSH_DEFAULT_MATCHING:
|
||||
add_refspec(":");
|
||||
break;
|
||||
|
||||
case PUSH_DEFAULT_TRACKING:
|
||||
setup_push_tracking();
|
||||
break;
|
||||
|
||||
case PUSH_DEFAULT_CURRENT:
|
||||
add_refspec("HEAD");
|
||||
break;
|
||||
|
||||
case PUSH_DEFAULT_NOTHING:
|
||||
die("You didn't specify any refspecs to push, and "
|
||||
"push.default is \"nothing\".");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_push(const char *repo, int flags)
|
||||
{
|
||||
int i, errs;
|
||||
@@ -79,11 +144,12 @@ static int do_push(const char *repo, int flags)
|
||||
return error("--all and --mirror are incompatible");
|
||||
}
|
||||
|
||||
if (!refspec
|
||||
&& !(flags & TRANSPORT_PUSH_ALL)
|
||||
&& remote->push_refspec_nr) {
|
||||
refspec = remote->push_refspec;
|
||||
refspec_nr = remote->push_refspec_nr;
|
||||
if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
|
||||
if (remote->push_refspec_nr) {
|
||||
refspec = remote->push_refspec;
|
||||
refspec_nr = remote->push_refspec_nr;
|
||||
} else if (!(flags & TRANSPORT_PUSH_MIRROR))
|
||||
setup_default_push_refspecs();
|
||||
}
|
||||
errs = 0;
|
||||
for (i = 0; i < remote->url_nr; i++) {
|
||||
|
||||
@@ -59,8 +59,7 @@ static int check_local_mod(unsigned char *head, int index_only)
|
||||
|
||||
if (lstat(ce->name, &st) < 0) {
|
||||
if (errno != ENOENT)
|
||||
fprintf(stderr, "warning: '%s': %s",
|
||||
ce->name, strerror(errno));
|
||||
warning("'%s': %s", ce->name, strerror(errno));
|
||||
/* It already vanished from the working tree */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,7 @@ static const char send_pack_usage[] =
|
||||
"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
|
||||
" --all and explicit <ref> specification are mutually exclusive.";
|
||||
|
||||
static struct send_pack_args args = {
|
||||
/* .receivepack = */ "git-receive-pack",
|
||||
};
|
||||
static struct send_pack_args args;
|
||||
|
||||
static int feed_object(const unsigned char *sha1, int fd, int negative)
|
||||
{
|
||||
@@ -31,7 +29,7 @@ static int feed_object(const unsigned char *sha1, int fd, int negative)
|
||||
/*
|
||||
* Make a pack stream and spit it out into file descriptor fd
|
||||
*/
|
||||
static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra)
|
||||
static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
|
||||
{
|
||||
/*
|
||||
* The child becomes pack-objects --revs; we feed
|
||||
@@ -49,7 +47,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
|
||||
struct child_process po;
|
||||
int i;
|
||||
|
||||
if (args.use_thin_pack)
|
||||
if (args->use_thin_pack)
|
||||
argv[4] = "--thin";
|
||||
memset(&po, 0, sizeof(po));
|
||||
po.argv = argv;
|
||||
@@ -83,8 +81,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ref *remote_refs, **remote_tail;
|
||||
|
||||
static int receive_status(int in, struct ref *refs)
|
||||
{
|
||||
struct ref *hint;
|
||||
@@ -172,16 +168,6 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *prettify_ref(const struct ref *ref)
|
||||
{
|
||||
const char *name = ref->name;
|
||||
return name + (
|
||||
!prefixcmp(name, "refs/heads/") ? 11 :
|
||||
!prefixcmp(name, "refs/tags/") ? 10 :
|
||||
!prefixcmp(name, "refs/remotes/") ? 13 :
|
||||
0);
|
||||
}
|
||||
|
||||
#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
|
||||
|
||||
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
|
||||
@@ -310,27 +296,19 @@ static int refs_pushed(struct ref *ref)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec)
|
||||
int send_pack(struct send_pack_args *args,
|
||||
int fd[], struct child_process *conn,
|
||||
struct ref *remote_refs,
|
||||
struct extra_have_objects *extra_have)
|
||||
{
|
||||
struct ref *ref, *local_refs;
|
||||
int in = fd[0];
|
||||
int out = fd[1];
|
||||
struct ref *ref;
|
||||
int new_refs;
|
||||
int ask_for_status_report = 0;
|
||||
int allow_deleting_refs = 0;
|
||||
int expect_status_report = 0;
|
||||
int flags = MATCH_REFS_NONE;
|
||||
int ret;
|
||||
struct extra_have_objects extra_have;
|
||||
|
||||
memset(&extra_have, 0, sizeof(extra_have));
|
||||
if (args.send_all)
|
||||
flags |= MATCH_REFS_ALL;
|
||||
if (args.send_mirror)
|
||||
flags |= MATCH_REFS_MIRROR;
|
||||
|
||||
/* No funny business with the matcher */
|
||||
remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL,
|
||||
&extra_have);
|
||||
local_refs = get_local_heads();
|
||||
|
||||
/* Does the other end support the reporting? */
|
||||
if (server_supports("report-status"))
|
||||
@@ -338,19 +316,9 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||
if (server_supports("delete-refs"))
|
||||
allow_deleting_refs = 1;
|
||||
|
||||
/* match them up */
|
||||
if (!remote_tail)
|
||||
remote_tail = &remote_refs;
|
||||
if (match_refs(local_refs, remote_refs, &remote_tail,
|
||||
nr_refspec, refspec, flags)) {
|
||||
close(out);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!remote_refs) {
|
||||
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
|
||||
"Perhaps you should specify a branch such as 'master'.\n");
|
||||
close(out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -362,7 +330,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||
|
||||
if (ref->peer_ref)
|
||||
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
|
||||
else if (!args.send_mirror)
|
||||
else if (!args->send_mirror)
|
||||
continue;
|
||||
|
||||
ref->deletion = is_null_sha1(ref->new_sha1);
|
||||
@@ -401,7 +369,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||
(!has_sha1_file(ref->old_sha1)
|
||||
|| !ref_newer(ref->new_sha1, ref->old_sha1));
|
||||
|
||||
if (ref->nonfastforward && !ref->force && !args.force_update) {
|
||||
if (ref->nonfastforward && !ref->force && !args->force_update) {
|
||||
ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
|
||||
continue;
|
||||
}
|
||||
@@ -409,7 +377,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||
if (!ref->deletion)
|
||||
new_refs++;
|
||||
|
||||
if (!args.dry_run) {
|
||||
if (!args->dry_run) {
|
||||
char *old_hex = sha1_to_hex(ref->old_sha1);
|
||||
char *new_hex = sha1_to_hex(ref->new_sha1);
|
||||
|
||||
@@ -430,27 +398,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||
}
|
||||
|
||||
packet_flush(out);
|
||||
if (new_refs && !args.dry_run) {
|
||||
if (pack_objects(out, remote_refs, &extra_have) < 0)
|
||||
if (new_refs && !args->dry_run) {
|
||||
if (pack_objects(out, remote_refs, extra_have, args) < 0) {
|
||||
for (ref = remote_refs; ref; ref = ref->next)
|
||||
ref->status = REF_STATUS_NONE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
close(out);
|
||||
|
||||
if (expect_status_report)
|
||||
ret = receive_status(in, remote_refs);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
print_push_status(dest, remote_refs);
|
||||
|
||||
if (!args.dry_run && remote) {
|
||||
for (ref = remote_refs; ref; ref = ref->next)
|
||||
update_tracking_ref(remote, ref);
|
||||
}
|
||||
|
||||
if (!refs_pushed(remote_refs))
|
||||
fprintf(stderr, "Everything up-to-date\n");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
for (ref = remote_refs; ref; ref = ref->next) {
|
||||
@@ -499,11 +459,19 @@ static void verify_remote_names(int nr_heads, const char **heads)
|
||||
|
||||
int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i, nr_heads = 0;
|
||||
const char **heads = NULL;
|
||||
int i, nr_refspecs = 0;
|
||||
const char **refspecs = NULL;
|
||||
const char *remote_name = NULL;
|
||||
struct remote *remote = NULL;
|
||||
const char *dest = NULL;
|
||||
int fd[2];
|
||||
struct child_process *conn;
|
||||
struct extra_have_objects extra_have;
|
||||
struct ref *remote_refs, **remote_tail, *local_refs;
|
||||
int ret;
|
||||
int send_all = 0;
|
||||
const char *receivepack = "git-receive-pack";
|
||||
int flags;
|
||||
|
||||
argv++;
|
||||
for (i = 1; i < argc; i++, argv++) {
|
||||
@@ -511,11 +479,11 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
|
||||
if (*arg == '-') {
|
||||
if (!prefixcmp(arg, "--receive-pack=")) {
|
||||
args.receivepack = arg + 15;
|
||||
receivepack = arg + 15;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--exec=")) {
|
||||
args.receivepack = arg + 7;
|
||||
receivepack = arg + 7;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--remote=")) {
|
||||
@@ -523,7 +491,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--all")) {
|
||||
args.send_all = 1;
|
||||
send_all = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--dry-run")) {
|
||||
@@ -552,8 +520,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
dest = arg;
|
||||
continue;
|
||||
}
|
||||
heads = (const char **) argv;
|
||||
nr_heads = argc - i;
|
||||
refspecs = (const char **) argv;
|
||||
nr_refspecs = argc - i;
|
||||
break;
|
||||
}
|
||||
if (!dest)
|
||||
@@ -562,8 +530,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
* --all and --mirror are incompatible; neither makes sense
|
||||
* with any refspecs.
|
||||
*/
|
||||
if ((heads && (args.send_all || args.send_mirror)) ||
|
||||
(args.send_all && args.send_mirror))
|
||||
if ((refspecs && (send_all || args.send_mirror)) ||
|
||||
(send_all && args.send_mirror))
|
||||
usage(send_pack_usage);
|
||||
|
||||
if (remote_name) {
|
||||
@@ -574,24 +542,50 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
}
|
||||
|
||||
return send_pack(&args, dest, remote, nr_heads, heads);
|
||||
}
|
||||
conn = git_connect(fd, dest, receivepack, args.verbose ? CONNECT_VERBOSE : 0);
|
||||
|
||||
int send_pack(struct send_pack_args *my_args,
|
||||
const char *dest, struct remote *remote,
|
||||
int nr_heads, const char **heads)
|
||||
{
|
||||
int fd[2], ret;
|
||||
struct child_process *conn;
|
||||
memset(&extra_have, 0, sizeof(extra_have));
|
||||
|
||||
memcpy(&args, my_args, sizeof(args));
|
||||
get_remote_heads(fd[0], &remote_refs, 0, NULL, REF_NORMAL,
|
||||
&extra_have);
|
||||
|
||||
verify_remote_names(nr_heads, heads);
|
||||
verify_remote_names(nr_refspecs, refspecs);
|
||||
|
||||
conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
|
||||
ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
|
||||
local_refs = get_local_heads();
|
||||
|
||||
flags = MATCH_REFS_NONE;
|
||||
|
||||
if (send_all)
|
||||
flags |= MATCH_REFS_ALL;
|
||||
if (args.send_mirror)
|
||||
flags |= MATCH_REFS_MIRROR;
|
||||
|
||||
/* match them up */
|
||||
remote_tail = &remote_refs;
|
||||
while (*remote_tail)
|
||||
remote_tail = &((*remote_tail)->next);
|
||||
if (match_refs(local_refs, remote_refs, &remote_tail,
|
||||
nr_refspecs, refspecs, flags)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
|
||||
|
||||
close(fd[1]);
|
||||
close(fd[0]);
|
||||
/* do_send_pack always closes fd[1] */
|
||||
|
||||
ret |= finish_connect(conn);
|
||||
return !!ret;
|
||||
|
||||
print_push_status(dest, remote_refs);
|
||||
|
||||
if (!args.dry_run && remote) {
|
||||
struct ref *ref;
|
||||
for (ref = remote_refs; ref; ref = ref->next)
|
||||
update_tracking_ref(remote, ref);
|
||||
}
|
||||
|
||||
if (!ret && !refs_pushed(remote_refs))
|
||||
fprintf(stderr, "Everything up-to-date\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -365,8 +365,7 @@ static int append_ref(const char *refname, const unsigned char *sha1,
|
||||
return 0;
|
||||
}
|
||||
if (MAX_REVS <= ref_name_cnt) {
|
||||
fprintf(stderr, "warning: ignoring %s; "
|
||||
"cannot handle more than %d refs\n",
|
||||
warning("ignoring %s; cannot handle more than %d refs",
|
||||
refname, MAX_REVS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ static int exclude_existing(const char *match)
|
||||
continue;
|
||||
}
|
||||
if (check_ref_format(ref)) {
|
||||
fprintf(stderr, "warning: ref '%s' ignored\n", ref);
|
||||
warning("ref '%s' ignored", ref);
|
||||
continue;
|
||||
}
|
||||
if (!string_list_has_string(&existing_refs, ref)) {
|
||||
|
||||
9
cache.h
9
cache.h
@@ -542,8 +542,17 @@ enum rebase_setup_type {
|
||||
AUTOREBASE_ALWAYS,
|
||||
};
|
||||
|
||||
enum push_default_type {
|
||||
PUSH_DEFAULT_UNSPECIFIED = -1,
|
||||
PUSH_DEFAULT_NOTHING = 0,
|
||||
PUSH_DEFAULT_MATCHING,
|
||||
PUSH_DEFAULT_TRACKING,
|
||||
PUSH_DEFAULT_CURRENT,
|
||||
};
|
||||
|
||||
extern enum branch_track git_branch_track;
|
||||
extern enum rebase_setup_type autorebase;
|
||||
extern enum push_default_type push_default;
|
||||
|
||||
#define GIT_REPO_VERSION 0
|
||||
extern int repository_format_version;
|
||||
|
||||
@@ -457,7 +457,7 @@ static const char *quote_arg(const char *arg)
|
||||
const char *p = arg;
|
||||
if (!*p) force_quotes = 1;
|
||||
while (*p) {
|
||||
if (isspace(*p) || *p == '*' || *p == '?' || *p == '{')
|
||||
if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
|
||||
force_quotes = 1;
|
||||
else if (*p == '"')
|
||||
n++;
|
||||
|
||||
28
config.c
28
config.c
@@ -565,6 +565,31 @@ static int git_default_branch_config(const char *var, const char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_default_push_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "push.default")) {
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
else if (!strcmp(value, "nothing"))
|
||||
push_default = PUSH_DEFAULT_NOTHING;
|
||||
else if (!strcmp(value, "matching"))
|
||||
push_default = PUSH_DEFAULT_MATCHING;
|
||||
else if (!strcmp(value, "tracking"))
|
||||
push_default = PUSH_DEFAULT_TRACKING;
|
||||
else if (!strcmp(value, "current"))
|
||||
push_default = PUSH_DEFAULT_CURRENT;
|
||||
else {
|
||||
error("Malformed value for %s: %s", var, value);
|
||||
return error("Must be one of nothing, matching, "
|
||||
"tracking or current.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add other config variables here and to Documentation/config.txt. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_default_mailmap_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "mailmap.file"))
|
||||
@@ -588,6 +613,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
|
||||
if (!prefixcmp(var, "branch."))
|
||||
return git_default_branch_config(var, value);
|
||||
|
||||
if (!prefixcmp(var, "push."))
|
||||
return git_default_push_config(var, value);
|
||||
|
||||
if (!prefixcmp(var, "mailmap."))
|
||||
return git_default_mailmap_config(var, value);
|
||||
|
||||
|
||||
@@ -899,7 +899,7 @@ _git_diff ()
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "--cached --pickaxe-all --pickaxe-regex
|
||||
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
|
||||
--base --ours --theirs
|
||||
$__git_diff_common_options
|
||||
"
|
||||
@@ -930,15 +930,21 @@ _git_format_patch ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--thread=*)
|
||||
__gitcomp "
|
||||
deep shallow
|
||||
" "" "${cur##--thread=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "
|
||||
--stdout --attach --thread
|
||||
--stdout --attach --no-attach --thread --thread=
|
||||
--output-directory
|
||||
--numbered --start-number
|
||||
--numbered-files
|
||||
--keep-subject
|
||||
--signoff
|
||||
--in-reply-to=
|
||||
--in-reply-to= --cc=
|
||||
--full-index --binary
|
||||
--not --all
|
||||
--cover-letter
|
||||
@@ -952,6 +958,21 @@ _git_format_patch ()
|
||||
__git_complete_revlist
|
||||
}
|
||||
|
||||
_git_fsck ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "
|
||||
--tags --root --unreachable --cache --no-reflogs --full
|
||||
--strict --verbose --lost-found
|
||||
"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=()
|
||||
}
|
||||
|
||||
_git_gc ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
@@ -1249,8 +1270,8 @@ _git_send_email ()
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "--bcc --cc --cc-cmd --chain-reply-to --compose
|
||||
--dry-run --envelope-sender --from --identity
|
||||
__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
|
||||
--compose --dry-run --envelope-sender --from --identity
|
||||
--in-reply-to --no-chain-reply-to --no-signed-off-by-cc
|
||||
--no-suppress-from --no-thread --quiet
|
||||
--signed-off-by-cc --smtp-pass --smtp-server
|
||||
@@ -1880,6 +1901,7 @@ _git ()
|
||||
diff) _git_diff ;;
|
||||
fetch) _git_fetch ;;
|
||||
format-patch) _git_format_patch ;;
|
||||
fsck) _git_fsck ;;
|
||||
gc) _git_gc ;;
|
||||
grep) _git_grep ;;
|
||||
help) _git_help ;;
|
||||
|
||||
@@ -205,8 +205,6 @@ void diff_no_index(struct rev_info *revs,
|
||||
no_index ? "--no-index" : "[--no-index]");
|
||||
|
||||
diff_setup(&revs->diffopt);
|
||||
if (!revs->diffopt.output_format)
|
||||
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
|
||||
for (i = 1; i < argc - 2; ) {
|
||||
int j;
|
||||
if (!strcmp(argv[i], "--no-index"))
|
||||
@@ -252,6 +250,8 @@ void diff_no_index(struct rev_info *revs,
|
||||
revs->diffopt.paths = argv + argc - 2;
|
||||
revs->diffopt.nr_paths = 2;
|
||||
revs->diffopt.skip_stat_unmatch = 1;
|
||||
if (!revs->diffopt.output_format)
|
||||
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
|
||||
|
||||
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
|
||||
DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
|
||||
|
||||
23
diff.c
23
diff.c
@@ -1757,7 +1757,8 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
|
||||
struct stat st;
|
||||
int pos, len;
|
||||
|
||||
/* We do not read the cache ourselves here, because the
|
||||
/*
|
||||
* We do not read the cache ourselves here, because the
|
||||
* benchmark with my previous version that always reads cache
|
||||
* shows that it makes things worse for diff-tree comparing
|
||||
* two linux-2.6 kernel trees in an already checked out work
|
||||
@@ -1797,6 +1798,13 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
|
||||
if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If ce is marked as "assume unchanged", there is no
|
||||
* guarantee that work tree matches what we are looking for.
|
||||
*/
|
||||
if (ce->ce_flags & CE_VALID)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If ce matches the file in the work tree, we can reuse it.
|
||||
*/
|
||||
@@ -1946,17 +1954,23 @@ void diff_free_filespec_data(struct diff_filespec *s)
|
||||
s->cnt_data = NULL;
|
||||
}
|
||||
|
||||
static void prep_temp_blob(struct diff_tempfile *temp,
|
||||
static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
|
||||
void *blob,
|
||||
unsigned long size,
|
||||
const unsigned char *sha1,
|
||||
int mode)
|
||||
{
|
||||
int fd;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
|
||||
if (fd < 0)
|
||||
die("unable to create temp-file: %s", strerror(errno));
|
||||
if (convert_to_working_tree(path,
|
||||
(const char *)blob, (size_t)size, &buf)) {
|
||||
blob = buf.buf;
|
||||
size = buf.len;
|
||||
}
|
||||
if (write_in_full(fd, blob, size) != size)
|
||||
die("unable to write temp-file");
|
||||
close(fd);
|
||||
@@ -1964,6 +1978,7 @@ static void prep_temp_blob(struct diff_tempfile *temp,
|
||||
strcpy(temp->hex, sha1_to_hex(sha1));
|
||||
temp->hex[40] = 0;
|
||||
sprintf(temp->mode, "%06o", mode);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
static struct diff_tempfile *prepare_temp_file(const char *name,
|
||||
@@ -2004,7 +2019,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
||||
die("readlink(%s)", name);
|
||||
if (ret == sizeof(buf))
|
||||
die("symlink too long: %s", name);
|
||||
prep_temp_blob(temp, buf, ret,
|
||||
prep_temp_blob(name, temp, buf, ret,
|
||||
(one->sha1_valid ?
|
||||
one->sha1 : null_sha1),
|
||||
(one->sha1_valid ?
|
||||
@@ -2030,7 +2045,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
||||
else {
|
||||
if (diff_populate_filespec(one, 0))
|
||||
die("cannot read data blob for %s", one->path);
|
||||
prep_temp_blob(temp, one->data, one->size,
|
||||
prep_temp_blob(name, temp, one->data, one->size,
|
||||
one->sha1, one->mode);
|
||||
}
|
||||
return temp;
|
||||
|
||||
@@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
|
||||
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
|
||||
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
|
||||
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
|
||||
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
|
||||
|
||||
/* Parallel index stat data preload? */
|
||||
int core_preload_index = 0;
|
||||
|
||||
@@ -61,6 +61,10 @@ const char *git_extract_argv0_path(const char *argv0)
|
||||
void git_set_argv_exec_path(const char *exec_path)
|
||||
{
|
||||
argv_exec_path = exec_path;
|
||||
/*
|
||||
* Propagate this setting to external programs.
|
||||
*/
|
||||
setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
(See Documentation/git-fast-import.txt for maintained documentation.)
|
||||
Format of STDIN stream:
|
||||
|
||||
stream ::= cmd*;
|
||||
@@ -18,8 +19,8 @@ Format of STDIN stream:
|
||||
|
||||
new_commit ::= 'commit' sp ref_str lf
|
||||
mark?
|
||||
('author' sp name '<' email '>' when lf)?
|
||||
'committer' sp name '<' email '>' when lf
|
||||
('author' sp name sp '<' email '>' sp when lf)?
|
||||
'committer' sp name sp '<' email '>' sp when lf
|
||||
commit_msg
|
||||
('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
|
||||
('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*
|
||||
@@ -43,7 +44,7 @@ Format of STDIN stream:
|
||||
|
||||
new_tag ::= 'tag' sp tag_str lf
|
||||
'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
|
||||
('tagger' sp name '<' email '>' when lf)?
|
||||
('tagger' sp name sp '<' email '>' sp when lf)?
|
||||
tag_msg;
|
||||
tag_msg ::= data;
|
||||
|
||||
|
||||
@@ -272,10 +272,10 @@ test $commits -eq 0 && die "Found nothing to rewrite"
|
||||
|
||||
# Rewrite the commits
|
||||
|
||||
i=0
|
||||
git_filter_branch__commit_count=0
|
||||
while read commit parents; do
|
||||
i=$(($i+1))
|
||||
printf "\rRewrite $commit ($i/$commits)"
|
||||
git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
|
||||
printf "\rRewrite $commit ($git_filter_branch__commit_count/$commits)"
|
||||
|
||||
case "$filter_subdir" in
|
||||
"")
|
||||
|
||||
@@ -319,7 +319,7 @@ do
|
||||
--root)
|
||||
rebase_root=t
|
||||
;;
|
||||
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force_rebas|--force-rebase)
|
||||
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
|
||||
force_rebase=t
|
||||
;;
|
||||
-*)
|
||||
|
||||
168
http-push.c
168
http-push.c
@@ -97,7 +97,7 @@ struct repo
|
||||
struct remote_lock *locks;
|
||||
};
|
||||
|
||||
static struct repo *remote;
|
||||
static struct repo *repo;
|
||||
|
||||
enum transfer_state {
|
||||
NEED_FETCH,
|
||||
@@ -324,7 +324,7 @@ static void start_fetch_loose(struct transfer_request *request)
|
||||
|
||||
git_SHA1_Init(&request->c);
|
||||
|
||||
url = get_remote_object_url(remote->url, hex, 0);
|
||||
url = get_remote_object_url(repo->url, hex, 0);
|
||||
request->url = xstrdup(url);
|
||||
|
||||
/* If a previous temp file is present, process what was already
|
||||
@@ -389,7 +389,7 @@ static void start_fetch_loose(struct transfer_request *request)
|
||||
request->state = RUN_FETCH_LOOSE;
|
||||
if (!start_active_slot(slot)) {
|
||||
fprintf(stderr, "Unable to start GET request\n");
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
release_request(request);
|
||||
}
|
||||
}
|
||||
@@ -399,7 +399,7 @@ static void start_mkcol(struct transfer_request *request)
|
||||
char *hex = sha1_to_hex(request->obj->sha1);
|
||||
struct active_request_slot *slot;
|
||||
|
||||
request->url = get_remote_object_url(remote->url, hex, 1);
|
||||
request->url = get_remote_object_url(repo->url, hex, 1);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->callback_func = process_response;
|
||||
@@ -434,10 +434,10 @@ static void start_fetch_packed(struct transfer_request *request)
|
||||
struct transfer_request *check_request = request_queue_head;
|
||||
struct active_request_slot *slot;
|
||||
|
||||
target = find_sha1_pack(request->obj->sha1, remote->packs);
|
||||
target = find_sha1_pack(request->obj->sha1, repo->packs);
|
||||
if (!target) {
|
||||
fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
release_request(request);
|
||||
return;
|
||||
}
|
||||
@@ -450,9 +450,9 @@ static void start_fetch_packed(struct transfer_request *request)
|
||||
snprintf(request->tmpfile, sizeof(request->tmpfile),
|
||||
"%s.temp", filename);
|
||||
|
||||
url = xmalloc(strlen(remote->url) + 64);
|
||||
url = xmalloc(strlen(repo->url) + 64);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.pack",
|
||||
remote->url, sha1_to_hex(target->sha1));
|
||||
repo->url, sha1_to_hex(target->sha1));
|
||||
|
||||
/* Make sure there isn't another open request for this pack */
|
||||
while (check_request) {
|
||||
@@ -469,7 +469,7 @@ static void start_fetch_packed(struct transfer_request *request)
|
||||
if (!packfile) {
|
||||
fprintf(stderr, "Unable to open local file %s for pack",
|
||||
request->tmpfile);
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
free(url);
|
||||
return;
|
||||
}
|
||||
@@ -505,7 +505,7 @@ static void start_fetch_packed(struct transfer_request *request)
|
||||
request->state = RUN_FETCH_PACKED;
|
||||
if (!start_active_slot(slot)) {
|
||||
fprintf(stderr, "Unable to start GET request\n");
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
release_request(request);
|
||||
}
|
||||
}
|
||||
@@ -554,10 +554,10 @@ static void start_put(struct transfer_request *request)
|
||||
request->buffer.buf.len = stream.total_out;
|
||||
|
||||
strbuf_addstr(&buf, "Destination: ");
|
||||
append_remote_object_url(&buf, remote->url, hex, 0);
|
||||
append_remote_object_url(&buf, repo->url, hex, 0);
|
||||
request->dest = strbuf_detach(&buf, NULL);
|
||||
|
||||
append_remote_object_url(&buf, remote->url, hex, 0);
|
||||
append_remote_object_url(&buf, repo->url, hex, 0);
|
||||
strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
|
||||
request->url = strbuf_detach(&buf, NULL);
|
||||
|
||||
@@ -648,7 +648,7 @@ static int refresh_lock(struct remote_lock *lock)
|
||||
|
||||
static void check_locks(void)
|
||||
{
|
||||
struct remote_lock *lock = remote->locks;
|
||||
struct remote_lock *lock = repo->locks;
|
||||
time_t current_time = time(NULL);
|
||||
int time_remaining;
|
||||
|
||||
@@ -759,7 +759,7 @@ static void finish_request(struct transfer_request *request)
|
||||
}
|
||||
} else {
|
||||
if (request->http_code == 416)
|
||||
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
|
||||
warning("requested range invalid; we may already have all the data.");
|
||||
|
||||
git_inflate_end(&request->stream);
|
||||
git_SHA1_Final(request->real_sha1, &request->c);
|
||||
@@ -788,7 +788,7 @@ static void finish_request(struct transfer_request *request)
|
||||
if (request->curl_result != CURLE_OK) {
|
||||
fprintf(stderr, "Unable to get pack file %s\n%s",
|
||||
request->url, curl_errorstr);
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
} else {
|
||||
off_t pack_size = ftell(request->local_stream);
|
||||
|
||||
@@ -798,7 +798,7 @@ static void finish_request(struct transfer_request *request)
|
||||
request->filename)) {
|
||||
target = (struct packed_git *)request->userData;
|
||||
target->pack_size = pack_size;
|
||||
lst = &remote->packs;
|
||||
lst = &repo->packs;
|
||||
while (*lst != target)
|
||||
lst = &((*lst)->next);
|
||||
*lst = (*lst)->next;
|
||||
@@ -806,7 +806,7 @@ static void finish_request(struct transfer_request *request)
|
||||
if (!verify_pack(target))
|
||||
install_packed_git(target);
|
||||
else
|
||||
remote->can_update_info_refs = 0;
|
||||
repo->can_update_info_refs = 0;
|
||||
}
|
||||
}
|
||||
release_request(request);
|
||||
@@ -889,7 +889,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
|
||||
get_remote_object_list(obj->sha1[0]);
|
||||
if (obj->flags & (REMOTE | PUSHING))
|
||||
return 0;
|
||||
target = find_sha1_pack(obj->sha1, remote->packs);
|
||||
target = find_sha1_pack(obj->sha1, repo->packs);
|
||||
if (target) {
|
||||
obj->flags |= REMOTE;
|
||||
return 0;
|
||||
@@ -930,8 +930,8 @@ static int fetch_index(unsigned char *sha1)
|
||||
struct slot_results results;
|
||||
|
||||
/* Don't use the index if the pack isn't there */
|
||||
url = xmalloc(strlen(remote->url) + 64);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
|
||||
url = xmalloc(strlen(repo->url) + 64);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
||||
@@ -956,7 +956,7 @@ static int fetch_index(unsigned char *sha1)
|
||||
if (push_verbosely)
|
||||
fprintf(stderr, "Getting index for pack %s\n", hex);
|
||||
|
||||
sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
|
||||
sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex);
|
||||
|
||||
filename = sha1_pack_index_name(sha1);
|
||||
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
|
||||
@@ -1018,8 +1018,8 @@ static int setup_index(unsigned char *sha1)
|
||||
return -1;
|
||||
|
||||
new_pack = parse_pack_index(sha1);
|
||||
new_pack->next = remote->packs;
|
||||
remote->packs = new_pack;
|
||||
new_pack->next = repo->packs;
|
||||
repo->packs = new_pack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1037,8 +1037,8 @@ static int fetch_indices(void)
|
||||
if (push_verbosely)
|
||||
fprintf(stderr, "Getting pack list\n");
|
||||
|
||||
url = xmalloc(strlen(remote->url) + 20);
|
||||
sprintf(url, "%sobjects/info/packs", remote->url);
|
||||
url = xmalloc(strlen(repo->url) + 20);
|
||||
sprintf(url, "%sobjects/info/packs", repo->url);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
@@ -1223,11 +1223,11 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
|
||||
struct curl_slist *dav_headers = NULL;
|
||||
struct xml_ctx ctx;
|
||||
|
||||
url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
/* Make sure leading directories exist for the remote ref */
|
||||
ep = strchr(url + strlen(remote->url) + 1, '/');
|
||||
ep = strchr(url + strlen(repo->url) + 1, '/');
|
||||
while (ep) {
|
||||
char saved_character = ep[1];
|
||||
ep[1] = '\0';
|
||||
@@ -1319,8 +1319,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
|
||||
} else {
|
||||
lock->url = url;
|
||||
lock->start_time = time(NULL);
|
||||
lock->next = remote->locks;
|
||||
remote->locks = lock;
|
||||
lock->next = repo->locks;
|
||||
repo->locks = lock;
|
||||
}
|
||||
|
||||
return lock;
|
||||
@@ -1330,7 +1330,7 @@ static int unlock_remote(struct remote_lock *lock)
|
||||
{
|
||||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
struct remote_lock *prev = remote->locks;
|
||||
struct remote_lock *prev = repo->locks;
|
||||
struct curl_slist *dav_headers;
|
||||
int rc = 0;
|
||||
|
||||
@@ -1356,8 +1356,8 @@ static int unlock_remote(struct remote_lock *lock)
|
||||
|
||||
curl_slist_free_all(dav_headers);
|
||||
|
||||
if (remote->locks == lock) {
|
||||
remote->locks = lock->next;
|
||||
if (repo->locks == lock) {
|
||||
repo->locks = lock->next;
|
||||
} else {
|
||||
while (prev && prev->next != lock)
|
||||
prev = prev->next;
|
||||
@@ -1375,7 +1375,7 @@ static int unlock_remote(struct remote_lock *lock)
|
||||
|
||||
static void remove_locks(void)
|
||||
{
|
||||
struct remote_lock *lock = remote->locks;
|
||||
struct remote_lock *lock = repo->locks;
|
||||
|
||||
fprintf(stderr, "Removing remote locks...\n");
|
||||
while (lock) {
|
||||
@@ -1457,7 +1457,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
|
||||
}
|
||||
}
|
||||
if (path) {
|
||||
path += remote->path_len;
|
||||
path += repo->path_len;
|
||||
ls->dentry_name = xstrdup(path);
|
||||
}
|
||||
} else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
|
||||
@@ -1480,7 +1480,7 @@ static void remote_ls(const char *path, int flags,
|
||||
void (*userFunc)(struct remote_ls_ctx *ls),
|
||||
void *userData)
|
||||
{
|
||||
char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
struct strbuf in_buffer = STRBUF_INIT;
|
||||
@@ -1496,7 +1496,7 @@ static void remote_ls(const char *path, int flags,
|
||||
ls.userData = userData;
|
||||
ls.userFunc = userFunc;
|
||||
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST);
|
||||
|
||||
@@ -1574,7 +1574,7 @@ static int locking_available(void)
|
||||
struct xml_ctx ctx;
|
||||
int lock_flags = 0;
|
||||
|
||||
strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
|
||||
strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, repo->url);
|
||||
|
||||
dav_headers = curl_slist_append(dav_headers, "Depth: 0");
|
||||
dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
|
||||
@@ -1586,7 +1586,7 @@ static int locking_available(void)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
|
||||
@@ -1616,16 +1616,16 @@ static int locking_available(void)
|
||||
}
|
||||
XML_ParserFree(parser);
|
||||
if (!lock_flags)
|
||||
error("Error: no DAV locking support on %s",
|
||||
remote->url);
|
||||
error("no DAV locking support on %s",
|
||||
repo->url);
|
||||
|
||||
} else {
|
||||
error("Cannot access URL %s, return code %d",
|
||||
remote->url, results.curl_result);
|
||||
repo->url, results.curl_result);
|
||||
lock_flags = 0;
|
||||
}
|
||||
} else {
|
||||
error("Unable to start PROPFIND request on %s", remote->url);
|
||||
error("Unable to start PROPFIND request on %s", repo->url);
|
||||
}
|
||||
|
||||
strbuf_release(&out_buffer.buf);
|
||||
@@ -1801,10 +1801,10 @@ static void one_remote_ref(char *refname)
|
||||
|
||||
ref = alloc_ref(refname);
|
||||
|
||||
if (http_fetch_ref(remote->url, ref) != 0) {
|
||||
if (http_fetch_ref(repo->url, ref) != 0) {
|
||||
fprintf(stderr,
|
||||
"Unable to fetch ref %s from %s\n",
|
||||
refname, remote->url);
|
||||
refname, repo->url);
|
||||
free(ref);
|
||||
return;
|
||||
}
|
||||
@@ -1813,7 +1813,7 @@ static void one_remote_ref(char *refname)
|
||||
* Fetch a copy of the object if it doesn't exist locally - it
|
||||
* may be required for updating server info later.
|
||||
*/
|
||||
if (remote->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
|
||||
if (repo->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
|
||||
obj = lookup_unknown_object(ref->old_sha1);
|
||||
if (obj) {
|
||||
fprintf(stderr, " fetch %s for %s\n",
|
||||
@@ -1853,10 +1853,10 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
|
||||
|
||||
ref = alloc_ref(ls->dentry_name);
|
||||
|
||||
if (http_fetch_ref(remote->url, ref) != 0) {
|
||||
if (http_fetch_ref(repo->url, ref) != 0) {
|
||||
fprintf(stderr,
|
||||
"Unable to fetch ref %s from %s\n",
|
||||
ls->dentry_name, remote->url);
|
||||
ls->dentry_name, repo->url);
|
||||
aborted = 1;
|
||||
free(ref);
|
||||
return;
|
||||
@@ -1931,12 +1931,12 @@ static void update_remote_info_refs(struct remote_lock *lock)
|
||||
|
||||
static int remote_exists(const char *path)
|
||||
{
|
||||
char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
int ret = -1;
|
||||
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
@@ -1966,8 +1966,8 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
|
||||
struct active_request_slot *slot;
|
||||
struct slot_results results;
|
||||
|
||||
url = xmalloc(strlen(remote->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", remote->url, path);
|
||||
url = xmalloc(strlen(repo->url) + strlen(path) + 1);
|
||||
sprintf(url, "%s%s", repo->url, path);
|
||||
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
@@ -2082,7 +2082,7 @@ static int delete_remote_branch(char *pattern, int force)
|
||||
"of your current HEAD.\n"
|
||||
"If you are sure you want to delete it,"
|
||||
" run:\n\t'git http-push -D %s %s'",
|
||||
remote_ref->name, remote->url, pattern);
|
||||
remote_ref->name, repo->url, pattern);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2090,8 +2090,8 @@ static int delete_remote_branch(char *pattern, int force)
|
||||
fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name);
|
||||
if (dry_run)
|
||||
return 0;
|
||||
url = xmalloc(strlen(remote->url) + strlen(remote_ref->name) + 1);
|
||||
sprintf(url, "%s%s", remote->url, remote_ref->name);
|
||||
url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1);
|
||||
sprintf(url, "%s%s", repo->url, remote_ref->name);
|
||||
slot = get_active_slot();
|
||||
slot->results = &results;
|
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
|
||||
@@ -2128,13 +2128,14 @@ int main(int argc, char **argv)
|
||||
int i;
|
||||
int new_refs;
|
||||
struct ref *ref, *local_refs;
|
||||
struct remote *remote;
|
||||
char *rewritten_url = NULL;
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
remote = xcalloc(sizeof(*remote), 1);
|
||||
repo = xcalloc(sizeof(*repo), 1);
|
||||
|
||||
argv++;
|
||||
for (i = 1; i < argc; i++, argv++) {
|
||||
@@ -2167,14 +2168,14 @@ int main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!remote->url) {
|
||||
if (!repo->url) {
|
||||
char *path = strstr(arg, "//");
|
||||
remote->url = arg;
|
||||
remote->path_len = strlen(arg);
|
||||
repo->url = arg;
|
||||
repo->path_len = strlen(arg);
|
||||
if (path) {
|
||||
remote->path = strchr(path+2, '/');
|
||||
if (remote->path)
|
||||
remote->path_len = strlen(remote->path);
|
||||
repo->path = strchr(path+2, '/');
|
||||
if (repo->path)
|
||||
repo->path_len = strlen(repo->path);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -2187,7 +2188,7 @@ int main(int argc, char **argv)
|
||||
die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI");
|
||||
#endif
|
||||
|
||||
if (!remote->url)
|
||||
if (!repo->url)
|
||||
usage(http_push_usage);
|
||||
|
||||
if (delete_branch && nr_refspec != 1)
|
||||
@@ -2195,17 +2196,24 @@ int main(int argc, char **argv)
|
||||
|
||||
memset(remote_dir_exists, -1, 256);
|
||||
|
||||
http_init(NULL);
|
||||
/*
|
||||
* Create a minimum remote by hand to give to http_init(),
|
||||
* primarily to allow it to look at the URL.
|
||||
*/
|
||||
remote = xcalloc(sizeof(*remote), 1);
|
||||
ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc);
|
||||
remote->url[remote->url_nr++] = repo->url;
|
||||
http_init(remote);
|
||||
|
||||
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
|
||||
|
||||
if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
|
||||
rewritten_url = xmalloc(strlen(remote->url)+2);
|
||||
strcpy(rewritten_url, remote->url);
|
||||
if (repo->url && repo->url[strlen(repo->url)-1] != '/') {
|
||||
rewritten_url = xmalloc(strlen(repo->url)+2);
|
||||
strcpy(rewritten_url, repo->url);
|
||||
strcat(rewritten_url, "/");
|
||||
remote->path = rewritten_url + (remote->path - remote->url);
|
||||
remote->path_len++;
|
||||
remote->url = rewritten_url;
|
||||
repo->path = rewritten_url + (repo->path - repo->url);
|
||||
repo->path_len++;
|
||||
repo->url = rewritten_url;
|
||||
}
|
||||
|
||||
/* Verify DAV compliance/lock support */
|
||||
@@ -2217,20 +2225,20 @@ int main(int argc, char **argv)
|
||||
sigchain_push_common(remove_locks_on_signal);
|
||||
|
||||
/* Check whether the remote has server info files */
|
||||
remote->can_update_info_refs = 0;
|
||||
remote->has_info_refs = remote_exists("info/refs");
|
||||
remote->has_info_packs = remote_exists("objects/info/packs");
|
||||
if (remote->has_info_refs) {
|
||||
repo->can_update_info_refs = 0;
|
||||
repo->has_info_refs = remote_exists("info/refs");
|
||||
repo->has_info_packs = remote_exists("objects/info/packs");
|
||||
if (repo->has_info_refs) {
|
||||
info_ref_lock = lock_remote("info/refs", LOCK_TIME);
|
||||
if (info_ref_lock)
|
||||
remote->can_update_info_refs = 1;
|
||||
repo->can_update_info_refs = 1;
|
||||
else {
|
||||
fprintf(stderr, "Error: cannot lock existing info/refs\n");
|
||||
error("cannot lock existing info/refs");
|
||||
rc = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (remote->has_info_packs)
|
||||
if (repo->has_info_packs)
|
||||
fetch_indices();
|
||||
|
||||
/* Get a list of all local and remote heads to validate refspecs */
|
||||
@@ -2388,8 +2396,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Update remote server info if appropriate */
|
||||
if (remote->has_info_refs && new_refs) {
|
||||
if (info_ref_lock && remote->can_update_info_refs) {
|
||||
if (repo->has_info_refs && new_refs) {
|
||||
if (info_ref_lock && repo->can_update_info_refs) {
|
||||
fprintf(stderr, "Updating remote server info\n");
|
||||
if (!dry_run)
|
||||
update_remote_info_refs(info_ref_lock);
|
||||
@@ -2402,7 +2410,7 @@ int main(int argc, char **argv)
|
||||
free(rewritten_url);
|
||||
if (info_ref_lock)
|
||||
unlock_remote(info_ref_lock);
|
||||
free(remote);
|
||||
free(repo);
|
||||
|
||||
curl_slist_free_all(no_pragma_header);
|
||||
|
||||
|
||||
169
http.c
169
http.c
@@ -1,7 +1,7 @@
|
||||
#include "http.h"
|
||||
|
||||
int data_received;
|
||||
int active_requests = 0;
|
||||
int active_requests;
|
||||
|
||||
#ifdef USE_CURL_MULTI
|
||||
static int max_requests = -1;
|
||||
@@ -13,22 +13,23 @@ static CURL *curl_default;
|
||||
char curl_errorstr[CURL_ERROR_SIZE];
|
||||
|
||||
static int curl_ssl_verify = -1;
|
||||
static const char *ssl_cert = NULL;
|
||||
static const char *ssl_cert;
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
static const char *ssl_key = NULL;
|
||||
static const char *ssl_key;
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||
static const char *ssl_capath = NULL;
|
||||
static const char *ssl_capath;
|
||||
#endif
|
||||
static const char *ssl_cainfo = NULL;
|
||||
static const char *ssl_cainfo;
|
||||
static long curl_low_speed_limit = -1;
|
||||
static long curl_low_speed_time = -1;
|
||||
static int curl_ftp_no_epsv = 0;
|
||||
static const char *curl_http_proxy = NULL;
|
||||
static int curl_ftp_no_epsv;
|
||||
static const char *curl_http_proxy;
|
||||
static char *user_name, *user_pass;
|
||||
|
||||
static struct curl_slist *pragma_header;
|
||||
|
||||
static struct active_request_slot *active_queue_head = NULL;
|
||||
static struct active_request_slot *active_queue_head;
|
||||
|
||||
size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
||||
{
|
||||
@@ -94,53 +95,33 @@ static void process_curl_messages(void)
|
||||
static int http_options(const char *var, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp("http.sslverify", var)) {
|
||||
if (curl_ssl_verify == -1) {
|
||||
curl_ssl_verify = git_config_bool(var, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp("http.sslcert", var)) {
|
||||
if (ssl_cert == NULL)
|
||||
return git_config_string(&ssl_cert, var, value);
|
||||
curl_ssl_verify = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.sslcert", var))
|
||||
return git_config_string(&ssl_cert, var, value);
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
if (!strcmp("http.sslkey", var)) {
|
||||
if (ssl_key == NULL)
|
||||
return git_config_string(&ssl_key, var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.sslkey", var))
|
||||
return git_config_string(&ssl_key, var, value);
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||
if (!strcmp("http.sslcapath", var)) {
|
||||
if (ssl_capath == NULL)
|
||||
return git_config_string(&ssl_capath, var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.sslcapath", var))
|
||||
return git_config_string(&ssl_capath, var, value);
|
||||
#endif
|
||||
if (!strcmp("http.sslcainfo", var)) {
|
||||
if (ssl_cainfo == NULL)
|
||||
return git_config_string(&ssl_cainfo, var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp("http.sslcainfo", var))
|
||||
return git_config_string(&ssl_cainfo, var, value);
|
||||
#ifdef USE_CURL_MULTI
|
||||
if (!strcmp("http.maxrequests", var)) {
|
||||
if (max_requests == -1)
|
||||
max_requests = git_config_int(var, value);
|
||||
max_requests = git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp("http.lowspeedlimit", var)) {
|
||||
if (curl_low_speed_limit == -1)
|
||||
curl_low_speed_limit = (long)git_config_int(var, value);
|
||||
curl_low_speed_limit = (long)git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.lowspeedtime", var)) {
|
||||
if (curl_low_speed_time == -1)
|
||||
curl_low_speed_time = (long)git_config_int(var, value);
|
||||
curl_low_speed_time = (long)git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -148,19 +129,28 @@ static int http_options(const char *var, const char *value, void *cb)
|
||||
curl_ftp_no_epsv = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.proxy", var)) {
|
||||
if (curl_http_proxy == NULL)
|
||||
return git_config_string(&curl_http_proxy, var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp("http.proxy", var))
|
||||
return git_config_string(&curl_http_proxy, var, value);
|
||||
|
||||
/* Fall back on the default ones */
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static CURL* get_curl_handle(void)
|
||||
static void init_curl_http_auth(CURL *result)
|
||||
{
|
||||
CURL* result = curl_easy_init();
|
||||
if (user_name) {
|
||||
struct strbuf up = STRBUF_INIT;
|
||||
if (!user_pass)
|
||||
user_pass = xstrdup(getpass("Password: "));
|
||||
strbuf_addf(&up, "%s:%s", user_name, user_pass);
|
||||
curl_easy_setopt(result, CURLOPT_USERPWD,
|
||||
strbuf_detach(&up, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
static CURL *get_curl_handle(void)
|
||||
{
|
||||
CURL *result = curl_easy_init();
|
||||
|
||||
if (!curl_ssl_verify) {
|
||||
curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
@@ -176,6 +166,8 @@ static CURL* get_curl_handle(void)
|
||||
curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
|
||||
#endif
|
||||
|
||||
init_curl_http_auth(result);
|
||||
|
||||
if (ssl_cert != NULL)
|
||||
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
@@ -213,11 +205,60 @@ static CURL* get_curl_handle(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
static void http_auth_init(const char *url)
|
||||
{
|
||||
char *at, *colon, *cp, *slash;
|
||||
int len;
|
||||
|
||||
cp = strstr(url, "://");
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ok, the URL looks like "proto://something". Which one?
|
||||
* "proto://<user>:<pass>@<host>/...",
|
||||
* "proto://<user>@<host>/...", or just
|
||||
* "proto://<host>/..."?
|
||||
*/
|
||||
cp += 3;
|
||||
at = strchr(cp, '@');
|
||||
colon = strchr(cp, ':');
|
||||
slash = strchrnul(cp, '/');
|
||||
if (!at || slash <= at)
|
||||
return; /* No credentials */
|
||||
if (!colon || at <= colon) {
|
||||
/* Only username */
|
||||
len = at - cp;
|
||||
user_name = xmalloc(len + 1);
|
||||
memcpy(user_name, cp, len);
|
||||
user_name[len] = '\0';
|
||||
user_pass = NULL;
|
||||
} else {
|
||||
len = colon - cp;
|
||||
user_name = xmalloc(len + 1);
|
||||
memcpy(user_name, cp, len);
|
||||
user_name[len] = '\0';
|
||||
len = at - (colon + 1);
|
||||
user_pass = xmalloc(len + 1);
|
||||
memcpy(user_pass, colon + 1, len);
|
||||
user_pass[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void set_from_env(const char **var, const char *envname)
|
||||
{
|
||||
const char *val = getenv(envname);
|
||||
if (val)
|
||||
*var = val;
|
||||
}
|
||||
|
||||
void http_init(struct remote *remote)
|
||||
{
|
||||
char *low_speed_limit;
|
||||
char *low_speed_time;
|
||||
|
||||
git_config(http_options, NULL);
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
if (remote && remote->http_proxy)
|
||||
@@ -242,14 +283,14 @@ void http_init(struct remote *remote)
|
||||
if (getenv("GIT_SSL_NO_VERIFY"))
|
||||
curl_ssl_verify = 0;
|
||||
|
||||
ssl_cert = getenv("GIT_SSL_CERT");
|
||||
set_from_env(&ssl_cert, "GIT_SSL_CERT");
|
||||
#if LIBCURL_VERSION_NUM >= 0x070902
|
||||
ssl_key = getenv("GIT_SSL_KEY");
|
||||
set_from_env(&ssl_key, "GIT_SSL_KEY");
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x070908
|
||||
ssl_capath = getenv("GIT_SSL_CAPATH");
|
||||
set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
|
||||
#endif
|
||||
ssl_cainfo = getenv("GIT_SSL_CAINFO");
|
||||
set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
|
||||
|
||||
low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
|
||||
if (low_speed_limit != NULL)
|
||||
@@ -258,8 +299,6 @@ void http_init(struct remote *remote)
|
||||
if (low_speed_time != NULL)
|
||||
curl_low_speed_time = strtol(low_speed_time, NULL, 10);
|
||||
|
||||
git_config(http_options, NULL);
|
||||
|
||||
if (curl_ssl_verify == -1)
|
||||
curl_ssl_verify = 1;
|
||||
|
||||
@@ -271,6 +310,9 @@ void http_init(struct remote *remote)
|
||||
if (getenv("GIT_CURL_FTP_NO_EPSV"))
|
||||
curl_ftp_no_epsv = 1;
|
||||
|
||||
if (remote && remote->url && remote->url[0])
|
||||
http_auth_init(remote->url[0]);
|
||||
|
||||
#ifndef NO_CURL_EASY_DUPHANDLE
|
||||
curl_default = get_curl_handle();
|
||||
#endif
|
||||
@@ -322,15 +364,14 @@ struct active_request_slot *get_active_slot(void)
|
||||
/* Wait for a slot to open up if the queue is full */
|
||||
while (active_requests >= max_requests) {
|
||||
curl_multi_perform(curlm, &num_transfers);
|
||||
if (num_transfers < active_requests) {
|
||||
if (num_transfers < active_requests)
|
||||
process_curl_messages();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (slot != NULL && slot->in_use) {
|
||||
while (slot != NULL && slot->in_use)
|
||||
slot = slot->next;
|
||||
}
|
||||
|
||||
if (slot == NULL) {
|
||||
newslot = xmalloc(sizeof(*newslot));
|
||||
newslot->curl = NULL;
|
||||
@@ -341,9 +382,8 @@ struct active_request_slot *get_active_slot(void)
|
||||
if (slot == NULL) {
|
||||
active_queue_head = newslot;
|
||||
} else {
|
||||
while (slot->next != NULL) {
|
||||
while (slot->next != NULL)
|
||||
slot = slot->next;
|
||||
}
|
||||
slot->next = newslot;
|
||||
}
|
||||
slot = newslot;
|
||||
@@ -404,7 +444,7 @@ struct fill_chain {
|
||||
struct fill_chain *next;
|
||||
};
|
||||
|
||||
static struct fill_chain *fill_cfg = NULL;
|
||||
static struct fill_chain *fill_cfg;
|
||||
|
||||
void add_fill_function(void *data, int (*fill)(void *))
|
||||
{
|
||||
@@ -535,9 +575,8 @@ static void finish_active_slot(struct active_request_slot *slot)
|
||||
}
|
||||
|
||||
/* Run callback if appropriate */
|
||||
if (slot->callback_func != NULL) {
|
||||
if (slot->callback_func != NULL)
|
||||
slot->callback_func(slot->callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void finish_all_active_slots(void)
|
||||
@@ -567,8 +606,10 @@ static inline int needs_quote(int ch)
|
||||
|
||||
static inline int hex(int v)
|
||||
{
|
||||
if (v < 10) return '0' + v;
|
||||
else return 'A' + v - 10;
|
||||
if (v < 10)
|
||||
return '0' + v;
|
||||
else
|
||||
return 'A' + v - 10;
|
||||
}
|
||||
|
||||
static char *quote_ref_url(const char *base, const char *ref)
|
||||
|
||||
@@ -242,7 +242,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
|
||||
}
|
||||
|
||||
void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
||||
int relative_date)
|
||||
enum date_mode dmode)
|
||||
{
|
||||
if (info && info->last_commit_reflog) {
|
||||
struct commit_reflog *commit_reflog = info->last_commit_reflog;
|
||||
@@ -251,8 +251,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
||||
info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
|
||||
if (oneline) {
|
||||
printf("%s@{", commit_reflog->reflogs->ref);
|
||||
if (commit_reflog->flag || relative_date)
|
||||
printf("%s", show_date(info->timestamp, 0, 1));
|
||||
if (commit_reflog->flag || dmode)
|
||||
printf("%s", show_date(info->timestamp,
|
||||
info->tz,
|
||||
dmode));
|
||||
else
|
||||
printf("%d", commit_reflog->reflogs->nr
|
||||
- 2 - commit_reflog->recno);
|
||||
@@ -260,10 +262,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline,
|
||||
}
|
||||
else {
|
||||
printf("Reflog: %s@{", commit_reflog->reflogs->ref);
|
||||
if (commit_reflog->flag || relative_date)
|
||||
if (commit_reflog->flag || dmode)
|
||||
printf("%s", show_date(info->timestamp,
|
||||
info->tz,
|
||||
relative_date));
|
||||
dmode));
|
||||
else
|
||||
printf("%d", commit_reflog->reflogs->nr
|
||||
- 2 - commit_reflog->recno);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#ifndef REFLOG_WALK_H
|
||||
#define REFLOG_WALK_H
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
extern void init_reflog_walk(struct reflog_walk_info** info);
|
||||
extern int add_reflog_for_walk(struct reflog_walk_info *info,
|
||||
struct commit *commit, const char *name);
|
||||
extern void fake_reflog_parent(struct reflog_walk_info *info,
|
||||
struct commit *commit);
|
||||
extern void show_reflog_message(struct reflog_walk_info *info, int, int);
|
||||
extern void show_reflog_message(struct reflog_walk_info *info, int,
|
||||
enum date_mode);
|
||||
|
||||
#endif
|
||||
|
||||
18
refs.c
18
refs.c
@@ -737,6 +737,16 @@ int check_ref_format(const char *ref)
|
||||
}
|
||||
}
|
||||
|
||||
const char *prettify_ref(const struct ref *ref)
|
||||
{
|
||||
const char *name = ref->name;
|
||||
return name + (
|
||||
!prefixcmp(name, "refs/heads/") ? 11 :
|
||||
!prefixcmp(name, "refs/tags/") ? 10 :
|
||||
!prefixcmp(name, "refs/remotes/") ? 13 :
|
||||
0);
|
||||
}
|
||||
|
||||
const char *ref_rev_parse_rules[] = {
|
||||
"%.*s",
|
||||
"refs/%.*s",
|
||||
@@ -996,7 +1006,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
|
||||
|
||||
err = unlink(git_path("logs/%s", lock->ref_name));
|
||||
if (err && errno != ENOENT)
|
||||
fprintf(stderr, "warning: unlink(%s) failed: %s",
|
||||
warning("unlink(%s) failed: %s",
|
||||
git_path("logs/%s", lock->ref_name), strerror(errno));
|
||||
invalidate_cached_refs();
|
||||
unlock_ref(lock);
|
||||
@@ -1438,8 +1448,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
|
||||
if (get_sha1_hex(rec + 41, sha1))
|
||||
die("Log %s is corrupt.", logfile);
|
||||
if (hashcmp(logged_sha1, sha1)) {
|
||||
fprintf(stderr,
|
||||
"warning: Log %s has gap after %s.\n",
|
||||
warning("Log %s has gap after %s.",
|
||||
logfile, show_date(date, tz, DATE_RFC2822));
|
||||
}
|
||||
}
|
||||
@@ -1451,8 +1460,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
|
||||
if (get_sha1_hex(rec + 41, logged_sha1))
|
||||
die("Log %s is corrupt.", logfile);
|
||||
if (hashcmp(logged_sha1, sha1)) {
|
||||
fprintf(stderr,
|
||||
"warning: Log %s unexpectedly ended on %s.\n",
|
||||
warning("Log %s unexpectedly ended on %s.",
|
||||
logfile, show_date(date, tz, DATE_RFC2822));
|
||||
}
|
||||
}
|
||||
|
||||
2
refs.h
2
refs.h
@@ -79,6 +79,8 @@ extern int for_each_reflog(each_ref_fn, void *);
|
||||
#define CHECK_REF_FORMAT_WILDCARD (-3)
|
||||
extern int check_ref_format(const char *target);
|
||||
|
||||
extern const char *prettify_ref(const struct ref *ref);
|
||||
|
||||
/** rename ref, return 0 on success **/
|
||||
extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
#define SEND_PACK_H
|
||||
|
||||
struct send_pack_args {
|
||||
const char *receivepack;
|
||||
unsigned verbose:1,
|
||||
send_all:1,
|
||||
send_mirror:1,
|
||||
force_update:1,
|
||||
use_thin_pack:1,
|
||||
@@ -12,7 +10,7 @@ struct send_pack_args {
|
||||
};
|
||||
|
||||
int send_pack(struct send_pack_args *args,
|
||||
const char *dest, struct remote *remote,
|
||||
int nr_heads, const char **heads);
|
||||
int fd[], struct child_process *conn,
|
||||
struct ref *remote_refs, struct extra_have_objects *extra_have);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2287,7 +2287,7 @@ static void close_sha1_file(int fd)
|
||||
fsync_or_die(fd, "sha1 file");
|
||||
fchmod(fd, 0444);
|
||||
if (close(fd) != 0)
|
||||
die("unable to write sha1 file");
|
||||
die("error when closing sha1 file (%s)", strerror(errno));
|
||||
}
|
||||
|
||||
/* Size of directory component, including the ending '/' */
|
||||
|
||||
@@ -24,7 +24,7 @@ pre-clean:
|
||||
$(RM) -r test-results
|
||||
|
||||
clean:
|
||||
$(RM) -r 'trash directory' test-results
|
||||
$(RM) -r 'trash directory'.* test-results
|
||||
|
||||
aggregate-results-and-cleanup: $(T)
|
||||
$(MAKE) aggregate-results
|
||||
|
||||
@@ -429,6 +429,37 @@ test_expect_success 'in-tree .gitattributes (4)' '
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'checkout with existing .gitattributes' '
|
||||
|
||||
git config core.autocrlf true &&
|
||||
git config --unset core.safecrlf &&
|
||||
echo ".file2 -crlfQ" | q_to_cr >> .gitattributes &&
|
||||
git add .gitattributes &&
|
||||
git commit -m initial &&
|
||||
echo ".file -crlfQ" | q_to_cr >> .gitattributes &&
|
||||
echo "contents" > .file &&
|
||||
git add .gitattributes .file &&
|
||||
git commit -m second &&
|
||||
|
||||
git checkout master~1 &&
|
||||
git checkout master &&
|
||||
test "$(git diff-files --raw)" = ""
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'checkout when deleting .gitattributes' '
|
||||
|
||||
git rm .gitattributes &&
|
||||
echo "contentsQ" | q_to_cr > .file2 &&
|
||||
git add .file2 &&
|
||||
git commit -m third
|
||||
|
||||
git checkout master~1 &&
|
||||
git checkout master &&
|
||||
remove_cr .file2 >/dev/null
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'invalid .gitattributes (must not crash)' '
|
||||
|
||||
echo "three +crlf" >>.gitattributes &&
|
||||
|
||||
@@ -17,7 +17,7 @@ norm_path() {
|
||||
# which means that the path / accounts for this many characters:
|
||||
rootoff=$(test-path-utils normalize_path_copy / | wc -c)
|
||||
# Account for the trailing LF:
|
||||
if test "$rootoff" = 2; then
|
||||
if test $rootoff = 2; then
|
||||
rootoff= # we are on Unix
|
||||
else
|
||||
rootoff=$(($rootoff-1))
|
||||
|
||||
67
t/t1411-reflog-show.sh
Executable file
67
t/t1411-reflog-show.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='Test reflog display routines'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
echo content >file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m one
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
|
||||
Reflog message: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'log -g shows reflog headers' '
|
||||
git log -g -1 >tmp &&
|
||||
grep ^Reflog <tmp >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
e46513e HEAD@{0}: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'oneline reflog format' '
|
||||
git log -g -1 --oneline >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>)
|
||||
Reflog message: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using @{now} syntax shows reflog date (multiline)' '
|
||||
git log -g -1 HEAD@{now} >tmp &&
|
||||
grep ^Reflog <tmp >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using @{now} syntax shows reflog date (oneline)' '
|
||||
git log -g -1 --oneline HEAD@{now} >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
Reflog: HEAD@{1112911993 -0700} (C O Mitter <committer@example.com>)
|
||||
Reflog message: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using --date= shows reflog date (multiline)' '
|
||||
git log -g -1 --date=raw >tmp &&
|
||||
grep ^Reflog <tmp >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
e46513e HEAD@{1112911993 -0700}: commit (initial): one
|
||||
EOF
|
||||
test_expect_success 'using --date= shows reflog date (oneline)' '
|
||||
git log -g -1 --oneline --date=raw >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
@@ -195,7 +195,7 @@ test_expect_success 'test deleting branch deletes branch config' \
|
||||
test_expect_success 'test deleting branch without config' \
|
||||
'git branch my7 s &&
|
||||
sha1=$(git rev-parse my7 | cut -c 1-7) &&
|
||||
test "$(git branch -d my7 2>&1)" = "Deleted branch my7 ($sha1)."'
|
||||
test "$(git branch -d my7 2>&1)" = "Deleted branch my7 (was $sha1)."'
|
||||
|
||||
test_expect_success 'test --track without .fetch entries' \
|
||||
'git branch --track my8 &&
|
||||
|
||||
@@ -136,4 +136,28 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
|
||||
GIT_EXTERNAL_DIFF=echo git diff
|
||||
'
|
||||
|
||||
echo "#!$SHELL_PATH" >fake-diff.sh
|
||||
cat >> fake-diff.sh <<\EOF
|
||||
cat $2 >> crlfed.txt
|
||||
EOF
|
||||
chmod a+x fake-diff.sh
|
||||
|
||||
keep_only_cr () {
|
||||
tr -dc '\015'
|
||||
}
|
||||
|
||||
test_expect_success 'external diff with autocrlf = true' '
|
||||
git config core.autocrlf true &&
|
||||
GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
|
||||
test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c)
|
||||
'
|
||||
|
||||
test_expect_success 'diff --cached' '
|
||||
git add file &&
|
||||
git update-index --assume-unchanged file &&
|
||||
echo second >file &&
|
||||
git diff --cached >actual &&
|
||||
test_cmp ../t4020/diff.NUL actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -7,6 +7,7 @@ test_description='GIT_EDITOR, core.editor, and stuff'
|
||||
for i in GIT_EDITOR core_editor EDITOR VISUAL vi
|
||||
do
|
||||
cat >e-$i.sh <<-EOF
|
||||
#!$SHELL_PATH
|
||||
echo "Edited by $i" >"\$1"
|
||||
EOF
|
||||
chmod +x e-$i.sh
|
||||
|
||||
@@ -234,7 +234,7 @@ cat >.git/FAKE_EDITOR <<EOF
|
||||
# kill -TERM command added below.
|
||||
EOF
|
||||
|
||||
test_expect_success 'a SIGTERM should break locks' '
|
||||
test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' '
|
||||
echo >>negative &&
|
||||
! "$SHELL_PATH" -c '\''
|
||||
echo kill -TERM $$ >> .git/FAKE_EDITOR
|
||||
|
||||
@@ -8,6 +8,9 @@ test_description='git fast-export'
|
||||
|
||||
test_expect_success 'setup' '
|
||||
|
||||
echo break it > file0 &&
|
||||
git add file0 &&
|
||||
test_tick &&
|
||||
echo Wohlauf > file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
@@ -57,8 +60,8 @@ test_expect_success 'fast-export master~2..master' '
|
||||
(cd new &&
|
||||
git fast-import &&
|
||||
test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
|
||||
git diff master..partial &&
|
||||
git diff master^..partial^ &&
|
||||
git diff --exit-code master partial &&
|
||||
git diff --exit-code master^ partial^ &&
|
||||
test_must_fail git rev-parse partial~2)
|
||||
|
||||
'
|
||||
|
||||
@@ -523,14 +523,6 @@ test_done () {
|
||||
fi
|
||||
case "$test_failure" in
|
||||
0)
|
||||
# We could:
|
||||
# cd .. && rm -fr 'trash directory'
|
||||
# but that means we forbid any tests that use their own
|
||||
# subdirectory from calling test_done without coming back
|
||||
# to where they started from.
|
||||
# The Makefile provided will clean this test area so
|
||||
# we will leave things as they are.
|
||||
|
||||
say_color pass "passed all $msg"
|
||||
|
||||
test -d "$remove_trash" &&
|
||||
@@ -697,10 +689,12 @@ case $(uname -s) in
|
||||
}
|
||||
# no POSIX permissions
|
||||
# backslashes in pathspec are converted to '/'
|
||||
# exec does not inherit the PID
|
||||
;;
|
||||
*)
|
||||
test_set_prereq POSIXPERM
|
||||
test_set_prereq BSLASHPSPEC
|
||||
test_set_prereq EXECKEEPSPID
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
283
transport.c
283
transport.c
@@ -143,7 +143,7 @@ static const char *rsync_url(const char *url)
|
||||
return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_rsync(struct transport *transport)
|
||||
static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
|
||||
struct ref dummy, *tail = &dummy;
|
||||
@@ -151,6 +151,9 @@ static struct ref *get_refs_via_rsync(struct transport *transport)
|
||||
const char *args[5];
|
||||
int temp_dir_len;
|
||||
|
||||
if (for_push)
|
||||
return NULL;
|
||||
|
||||
/* copy the refs to the temporary directory */
|
||||
|
||||
strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
|
||||
@@ -429,7 +432,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
|
||||
return !!err;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_curl(struct transport *transport)
|
||||
static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
|
||||
{
|
||||
struct strbuf buffer = STRBUF_INIT;
|
||||
char *data, *start, *mid;
|
||||
@@ -446,6 +449,9 @@ static struct ref *get_refs_via_curl(struct transport *transport)
|
||||
|
||||
struct walker *walker;
|
||||
|
||||
if (for_push)
|
||||
return NULL;
|
||||
|
||||
if (!transport->data)
|
||||
transport->data = get_http_walker(transport->url,
|
||||
transport->remote);
|
||||
@@ -532,12 +538,15 @@ struct bundle_transport_data {
|
||||
struct bundle_header header;
|
||||
};
|
||||
|
||||
static struct ref *get_refs_from_bundle(struct transport *transport)
|
||||
static struct ref *get_refs_from_bundle(struct transport *transport, int for_push)
|
||||
{
|
||||
struct bundle_transport_data *data = transport->data;
|
||||
struct ref *result = NULL;
|
||||
int i;
|
||||
|
||||
if (for_push)
|
||||
return NULL;
|
||||
|
||||
if (data->fd > 0)
|
||||
close(data->fd);
|
||||
data->fd = read_bundle_header(transport->url, &data->header);
|
||||
@@ -578,6 +587,7 @@ struct git_transport_data {
|
||||
int fd[2];
|
||||
const char *uploadpack;
|
||||
const char *receivepack;
|
||||
struct extra_have_objects extra_have;
|
||||
};
|
||||
|
||||
static int set_git_option(struct transport *connection,
|
||||
@@ -609,20 +619,23 @@ static int set_git_option(struct transport *connection,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int connect_setup(struct transport *transport)
|
||||
static int connect_setup(struct transport *transport, int for_push, int verbose)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0);
|
||||
data->conn = git_connect(data->fd, transport->url,
|
||||
for_push ? data->receivepack : data->uploadpack,
|
||||
verbose ? CONNECT_VERBOSE : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ref *get_refs_via_connect(struct transport *transport)
|
||||
static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
struct ref *refs;
|
||||
|
||||
connect_setup(transport);
|
||||
get_remote_heads(data->fd[0], &refs, 0, NULL, 0, NULL);
|
||||
connect_setup(transport, for_push, 0);
|
||||
get_remote_heads(data->fd[0], &refs, 0, NULL,
|
||||
for_push ? REF_NORMAL : 0, &data->extra_have);
|
||||
|
||||
return refs;
|
||||
}
|
||||
@@ -654,7 +667,7 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
|
||||
|
||||
if (!data->conn) {
|
||||
connect_setup(transport);
|
||||
connect_setup(transport, 0, 0);
|
||||
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
@@ -677,20 +690,216 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||
return (refs ? 0 : -1);
|
||||
}
|
||||
|
||||
static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
|
||||
static int refs_pushed(struct ref *ref)
|
||||
{
|
||||
for (; ref; ref = ref->next) {
|
||||
switch(ref->status) {
|
||||
case REF_STATUS_NONE:
|
||||
case REF_STATUS_UPTODATE:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
|
||||
{
|
||||
struct refspec rs;
|
||||
|
||||
if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
|
||||
return;
|
||||
|
||||
rs.src = ref->name;
|
||||
rs.dst = NULL;
|
||||
|
||||
if (!remote_find_tracking(remote, &rs)) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
|
||||
if (ref->deletion) {
|
||||
delete_ref(rs.dst, NULL, 0);
|
||||
} else
|
||||
update_ref("update by push", rs.dst,
|
||||
ref->new_sha1, NULL, 0, 0);
|
||||
free(rs.dst);
|
||||
}
|
||||
}
|
||||
|
||||
#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
|
||||
|
||||
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
|
||||
{
|
||||
fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
|
||||
if (from)
|
||||
fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to));
|
||||
else
|
||||
fputs(prettify_ref(to), stderr);
|
||||
if (msg) {
|
||||
fputs(" (", stderr);
|
||||
fputs(msg, stderr);
|
||||
fputc(')', stderr);
|
||||
}
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
static const char *status_abbrev(unsigned char sha1[20])
|
||||
{
|
||||
return find_unique_abbrev(sha1, DEFAULT_ABBREV);
|
||||
}
|
||||
|
||||
static void print_ok_ref_status(struct ref *ref)
|
||||
{
|
||||
if (ref->deletion)
|
||||
print_ref_status('-', "[deleted]", ref, NULL, NULL);
|
||||
else if (is_null_sha1(ref->old_sha1))
|
||||
print_ref_status('*',
|
||||
(!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
|
||||
"[new branch]"),
|
||||
ref, ref->peer_ref, NULL);
|
||||
else {
|
||||
char quickref[84];
|
||||
char type;
|
||||
const char *msg;
|
||||
|
||||
strcpy(quickref, status_abbrev(ref->old_sha1));
|
||||
if (ref->nonfastforward) {
|
||||
strcat(quickref, "...");
|
||||
type = '+';
|
||||
msg = "forced update";
|
||||
} else {
|
||||
strcat(quickref, "..");
|
||||
type = ' ';
|
||||
msg = NULL;
|
||||
}
|
||||
strcat(quickref, status_abbrev(ref->new_sha1));
|
||||
|
||||
print_ref_status(type, quickref, ref, ref->peer_ref, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static int print_one_push_status(struct ref *ref, const char *dest, int count)
|
||||
{
|
||||
if (!count)
|
||||
fprintf(stderr, "To %s\n", dest);
|
||||
|
||||
switch(ref->status) {
|
||||
case REF_STATUS_NONE:
|
||||
print_ref_status('X', "[no match]", ref, NULL, NULL);
|
||||
break;
|
||||
case REF_STATUS_REJECT_NODELETE:
|
||||
print_ref_status('!', "[rejected]", ref, NULL,
|
||||
"remote does not support deleting refs");
|
||||
break;
|
||||
case REF_STATUS_UPTODATE:
|
||||
print_ref_status('=', "[up to date]", ref,
|
||||
ref->peer_ref, NULL);
|
||||
break;
|
||||
case REF_STATUS_REJECT_NONFASTFORWARD:
|
||||
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
|
||||
"non-fast forward");
|
||||
break;
|
||||
case REF_STATUS_REMOTE_REJECT:
|
||||
print_ref_status('!', "[remote rejected]", ref,
|
||||
ref->deletion ? NULL : ref->peer_ref,
|
||||
ref->remote_status);
|
||||
break;
|
||||
case REF_STATUS_EXPECTING_REPORT:
|
||||
print_ref_status('!', "[remote failure]", ref,
|
||||
ref->deletion ? NULL : ref->peer_ref,
|
||||
"remote failed to report status");
|
||||
break;
|
||||
case REF_STATUS_OK:
|
||||
print_ok_ref_status(ref);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_push_status(const char *dest, struct ref *refs, int verbose)
|
||||
{
|
||||
struct ref *ref;
|
||||
int n = 0;
|
||||
|
||||
if (verbose) {
|
||||
for (ref = refs; ref; ref = ref->next)
|
||||
if (ref->status == REF_STATUS_UPTODATE)
|
||||
n += print_one_push_status(ref, dest, n);
|
||||
}
|
||||
|
||||
for (ref = refs; ref; ref = ref->next)
|
||||
if (ref->status == REF_STATUS_OK)
|
||||
n += print_one_push_status(ref, dest, n);
|
||||
|
||||
for (ref = refs; ref; ref = ref->next) {
|
||||
if (ref->status != REF_STATUS_NONE &&
|
||||
ref->status != REF_STATUS_UPTODATE &&
|
||||
ref->status != REF_STATUS_OK)
|
||||
n += print_one_push_status(ref, dest, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void verify_remote_names(int nr_heads, const char **heads)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_heads; i++) {
|
||||
const char *local = heads[i];
|
||||
const char *remote = strrchr(heads[i], ':');
|
||||
|
||||
if (*local == '+')
|
||||
local++;
|
||||
|
||||
/* A matching refspec is okay. */
|
||||
if (remote == local && remote[1] == '\0')
|
||||
continue;
|
||||
|
||||
remote = remote ? (remote + 1) : local;
|
||||
switch (check_ref_format(remote)) {
|
||||
case 0: /* ok */
|
||||
case CHECK_REF_FORMAT_ONELEVEL:
|
||||
/* ok but a single level -- that is fine for
|
||||
* a match pattern.
|
||||
*/
|
||||
case CHECK_REF_FORMAT_WILDCARD:
|
||||
/* ok but ends with a pattern-match character */
|
||||
continue;
|
||||
}
|
||||
die("remote part of refspec is not a valid name in %s",
|
||||
heads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
struct send_pack_args args;
|
||||
int ret;
|
||||
|
||||
if (!data->conn) {
|
||||
struct ref *tmp_refs;
|
||||
connect_setup(transport, 1, 0);
|
||||
|
||||
get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
args.receivepack = data->receivepack;
|
||||
args.send_all = !!(flags & TRANSPORT_PUSH_ALL);
|
||||
args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
|
||||
args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
|
||||
args.use_thin_pack = data->thin;
|
||||
args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
|
||||
args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
|
||||
|
||||
return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec);
|
||||
ret = send_pack(&args, data->fd, data->conn, remote_refs,
|
||||
&data->extra_have);
|
||||
|
||||
close(data->fd[1]);
|
||||
close(data->fd[0]);
|
||||
ret |= finish_connect(data->conn);
|
||||
data->conn = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int disconnect_git(struct transport *transport)
|
||||
@@ -760,7 +969,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
||||
ret->set_option = set_git_option;
|
||||
ret->get_refs_list = get_refs_via_connect;
|
||||
ret->fetch = fetch_refs_via_pack;
|
||||
ret->push = git_transport_push;
|
||||
ret->push_refs = git_transport_push;
|
||||
ret->disconnect = disconnect_git;
|
||||
|
||||
data->thin = 1;
|
||||
@@ -787,15 +996,53 @@ int transport_set_option(struct transport *transport,
|
||||
int transport_push(struct transport *transport,
|
||||
int refspec_nr, const char **refspec, int flags)
|
||||
{
|
||||
if (!transport->push)
|
||||
return 1;
|
||||
return transport->push(transport, refspec_nr, refspec, flags);
|
||||
verify_remote_names(refspec_nr, refspec);
|
||||
|
||||
if (transport->push)
|
||||
return transport->push(transport, refspec_nr, refspec, flags);
|
||||
if (transport->push_refs) {
|
||||
struct ref *remote_refs =
|
||||
transport->get_refs_list(transport, 1);
|
||||
struct ref **remote_tail;
|
||||
struct ref *local_refs = get_local_heads();
|
||||
int match_flags = MATCH_REFS_NONE;
|
||||
int verbose = flags & TRANSPORT_PUSH_VERBOSE;
|
||||
int ret;
|
||||
|
||||
if (flags & TRANSPORT_PUSH_ALL)
|
||||
match_flags |= MATCH_REFS_ALL;
|
||||
if (flags & TRANSPORT_PUSH_MIRROR)
|
||||
match_flags |= MATCH_REFS_MIRROR;
|
||||
|
||||
remote_tail = &remote_refs;
|
||||
while (*remote_tail)
|
||||
remote_tail = &((*remote_tail)->next);
|
||||
if (match_refs(local_refs, remote_refs, &remote_tail,
|
||||
refspec_nr, refspec, match_flags)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = transport->push_refs(transport, remote_refs, flags);
|
||||
|
||||
print_push_status(transport->url, remote_refs, verbose);
|
||||
|
||||
if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
|
||||
struct ref *ref;
|
||||
for (ref = remote_refs; ref; ref = ref->next)
|
||||
update_tracking_ref(transport->remote, ref, verbose);
|
||||
}
|
||||
|
||||
if (!ret && !refs_pushed(remote_refs))
|
||||
fprintf(stderr, "Everything up-to-date\n");
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct ref *transport_get_remote_refs(struct transport *transport)
|
||||
{
|
||||
if (!transport->remote_refs)
|
||||
transport->remote_refs = transport->get_refs_list(transport);
|
||||
transport->remote_refs = transport->get_refs_list(transport, 0);
|
||||
return transport->remote_refs;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@ struct transport {
|
||||
int (*set_option)(struct transport *connection, const char *name,
|
||||
const char *value);
|
||||
|
||||
struct ref *(*get_refs_list)(struct transport *transport);
|
||||
struct ref *(*get_refs_list)(struct transport *transport, int for_push);
|
||||
int (*fetch)(struct transport *transport, int refs_nr, const struct ref **refs);
|
||||
int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
|
||||
int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
|
||||
|
||||
int (*disconnect)(struct transport *connection);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "unpack-trees.h"
|
||||
#include "progress.h"
|
||||
#include "refs.h"
|
||||
#include "attr.h"
|
||||
|
||||
/*
|
||||
* Error messages expected by scripts out of plumbing commands such as
|
||||
@@ -86,6 +87,7 @@ static int check_updates(struct unpack_trees_options *o)
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
|
||||
for (i = 0; i < index->cache_nr; i++) {
|
||||
struct cache_entry *ce = index->cache[i];
|
||||
|
||||
@@ -110,6 +112,7 @@ static int check_updates(struct unpack_trees_options *o)
|
||||
}
|
||||
}
|
||||
stop_progress(&progress);
|
||||
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
|
||||
return errs != 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user