mirror of
https://github.com/git/git.git
synced 2026-04-01 20:40:08 +02:00
Merge branch 'master' of git://repo.or.cz/alt-git
This commit is contained in:
51
Documentation/RelNotes-1.6.5.txt
Normal file
51
Documentation/RelNotes-1.6.5.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
GIT v1.6.5 Release Notes
|
||||
========================
|
||||
|
||||
In git 1.7.0, which is planned to be the release after 1.6.5, "git push"
|
||||
into a branch that is currently checked out will be refused by default.
|
||||
|
||||
You can choose what should happen upon such a push by setting the
|
||||
configuration variable receive.denyCurrentBranch in the receiving
|
||||
repository.
|
||||
|
||||
Also, "git push $there :$killed" to delete the branch $killed in a remote
|
||||
repository $there, when $killed branch is the current branch pointed at by
|
||||
its HEAD, will be refused by default.
|
||||
|
||||
You can choose what should happen upon such a push by setting the
|
||||
configuration variable receive.denyDeleteCurrent in the receiving
|
||||
repository.
|
||||
|
||||
To ease the transition plan, the receiving repository of such a
|
||||
push running this release will issue a big warning when the
|
||||
configuration variable is missing. Please refer to:
|
||||
|
||||
http://git.or.cz/gitwiki/GitFaq#non-bare
|
||||
http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
|
||||
|
||||
for more details on the reason why this change is needed and the
|
||||
transition plan.
|
||||
|
||||
Updates since v1.6.4
|
||||
--------------------
|
||||
|
||||
(subsystems)
|
||||
|
||||
(portability)
|
||||
|
||||
(performance)
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
(developers)
|
||||
|
||||
Fixes since v1.6.4
|
||||
------------------
|
||||
|
||||
# All of the fixes in v1.6.4.X maintenance series are included in this
|
||||
# release, unless otherwise noted.
|
||||
|
||||
# Here are fixes that this release has, but have not been backported to
|
||||
# v1.6.4.X series.
|
||||
|
||||
|
||||
@@ -605,7 +605,7 @@ color.interactive.<slot>::
|
||||
Use customized color for 'git-add --interactive'
|
||||
output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
|
||||
four distinct types of normal output from interactive
|
||||
programs. The values of these variables may be specified as
|
||||
commands. The values of these variables may be specified as
|
||||
in color.branch.<slot>.
|
||||
|
||||
color.pager::
|
||||
@@ -1113,7 +1113,7 @@ instaweb.port::
|
||||
linkgit:git-instaweb[1].
|
||||
|
||||
interactive.singlekey::
|
||||
In interactive programs, allow the user to provide one-letter
|
||||
In interactive commands, allow the user to provide one-letter
|
||||
input with a single key (i.e., without hitting enter).
|
||||
Currently this is used only by the `\--patch` mode of
|
||||
linkgit:git-add[1]. Note that this setting is silently
|
||||
@@ -1218,12 +1218,20 @@ pack.compression::
|
||||
|
||||
pack.deltaCacheSize::
|
||||
The maximum memory in bytes used for caching deltas in
|
||||
linkgit:git-pack-objects[1].
|
||||
A value of 0 means no limit. Defaults to 0.
|
||||
linkgit:git-pack-objects[1] before writing them out to a pack.
|
||||
This cache is used to speed up the writing object phase by not
|
||||
having to recompute the final delta result once the best match
|
||||
for all objects is found. Repacking large repositories on machines
|
||||
which are tight with memory might be badly impacted by this though,
|
||||
especially if this cache pushes the system into swapping.
|
||||
A value of 0 means no limit. The smallest size of 1 byte may be
|
||||
used to virtually disable this cache. Defaults to 256 MiB.
|
||||
|
||||
pack.deltaCacheLimit::
|
||||
The maximum size of a delta, that is cached in
|
||||
linkgit:git-pack-objects[1]. Defaults to 1000.
|
||||
linkgit:git-pack-objects[1]. This cache is used to speed up the
|
||||
writing object phase by not having to recompute the final delta
|
||||
result once the best match for all objects is found. Defaults to 1000.
|
||||
|
||||
pack.threads::
|
||||
Specifies the number of threads to spawn when searching for best
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-q::
|
||||
--quiet::
|
||||
Pass --quiet to git-fetch-pack and silence any other internally
|
||||
used programs.
|
||||
used git commands.
|
||||
|
||||
-v::
|
||||
--verbose::
|
||||
|
||||
@@ -10,7 +10,7 @@ SYNOPSIS
|
||||
[verse]
|
||||
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
|
||||
[--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
|
||||
[--refresh] [--ignore-errors] [--] <filepattern>...
|
||||
[--refresh] [--ignore-errors] [--] [<filepattern>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
@@ -27,6 +27,9 @@ OPTIONS
|
||||
-------
|
||||
-d::
|
||||
Remove untracked directories in addition to untracked files.
|
||||
If an untracked directory is managed by a different git
|
||||
repository, it is not removed by default. Use -f option twice
|
||||
if you really want to remove such a directory.
|
||||
|
||||
-f::
|
||||
If the git configuration specifies clean.requireForce as true,
|
||||
|
||||
@@ -82,6 +82,14 @@ marks the same across runs.
|
||||
allow that. So fake a tagger to be able to fast-import the
|
||||
output.
|
||||
|
||||
--no-data::
|
||||
Skip output of blob objects and instead refer to blobs via
|
||||
their original SHA-1 hash. This is useful when rewriting the
|
||||
directory structure or history of a repository without
|
||||
touching the contents of individual files. Note that the
|
||||
resulting stream can only be used by a repository which
|
||||
already contains the necessary objects.
|
||||
|
||||
[git-rev-list-args...]::
|
||||
A list of arguments, acceptable to 'git-rev-parse' and
|
||||
'git-rev-list', that specifies the specific objects and references
|
||||
|
||||
@@ -17,6 +17,7 @@ SYNOPSIS
|
||||
[-l | --files-with-matches] [-L | --files-without-match]
|
||||
[-z | --null]
|
||||
[-c | --count] [--all-match]
|
||||
[--max-depth <depth>]
|
||||
[--color | --no-color]
|
||||
[-A <post-context>] [-B <pre-context>] [-C <context>]
|
||||
[-f <file>] [-e] <pattern>
|
||||
@@ -47,6 +48,10 @@ OPTIONS
|
||||
-I::
|
||||
Don't match the pattern in binary files.
|
||||
|
||||
--max-depth <depth>::
|
||||
For each pathspec given on command line, descend at most <depth>
|
||||
levels of directories. A negative value means no limit.
|
||||
|
||||
-w::
|
||||
--word-regexp::
|
||||
Match the pattern only at word boundary (either begin at the
|
||||
|
||||
@@ -8,7 +8,7 @@ git-init-db - Creates an empty git repository
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git init-db' [-q | --quiet] [--template=<template_directory>] [--shared[=<permissions>]]
|
||||
'git init-db' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@@ -8,7 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
|
||||
'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]] [directory]
|
||||
|
||||
|
||||
OPTIONS
|
||||
@@ -74,6 +74,9 @@ By default, the configuration flag receive.denyNonFastForwards is enabled
|
||||
in shared repositories, so that you cannot force a non fast-forwarding push
|
||||
into it.
|
||||
|
||||
If you name a (possibly non-existent) directory at the end of the command
|
||||
line, the command is run inside the directory (possibly after creating it).
|
||||
|
||||
--
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ OPTIONS
|
||||
|
||||
-o::
|
||||
--others::
|
||||
Show other files in the output
|
||||
Show other (i.e. untracked) files in the output
|
||||
|
||||
-i::
|
||||
--ignored::
|
||||
|
||||
@@ -8,12 +8,12 @@ git-merge-base - Find as good common ancestors as possible for a merge
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git merge-base' [--all] <commit> <commit>...
|
||||
'git merge-base' [-a|--all] <commit> <commit>...
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
'git-merge-base' finds best common ancestor(s) between two commits to use
|
||||
'git merge-base' finds best common ancestor(s) between two commits to use
|
||||
in a three-way merge. One common ancestor is 'better' than another common
|
||||
ancestor if the latter is an ancestor of the former. A common ancestor
|
||||
that does not have any better common ancestor is a 'best common
|
||||
@@ -27,8 +27,13 @@ commits on the command line. As the most common special case, specifying only
|
||||
two commits on the command line means computing the merge base between
|
||||
the given two commits.
|
||||
|
||||
As a consequence, the 'merge base' is not necessarily contained in each of the
|
||||
commit arguments if more than two commits are specified. This is different
|
||||
from linkgit:git-show-branch[1] when used with the `--merge-base` option.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-a::
|
||||
--all::
|
||||
Output all merge bases for the commits, instead of just one.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
|
||||
[-m <msg>] <remote> <remote>...
|
||||
[-m <msg>] <remote>...
|
||||
'git merge' <msg> HEAD <remote>...
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@@ -8,7 +8,7 @@ git-prune-packed - Remove extra objects that are already in pack files
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git prune-packed' [-n] [-q]
|
||||
'git prune-packed' [-n|--dry-run] [-q|--quiet]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
@@ -28,10 +28,12 @@ disk storage, etc.
|
||||
OPTIONS
|
||||
-------
|
||||
-n::
|
||||
--dry-run::
|
||||
Don't actually remove any objects, only show those that would have been
|
||||
removed.
|
||||
|
||||
-q::
|
||||
--quiet::
|
||||
Squelch the progress indicator.
|
||||
|
||||
Author
|
||||
|
||||
@@ -195,6 +195,92 @@ reason::
|
||||
refs, no explanation is needed. For a failed ref, the reason for
|
||||
failure is described.
|
||||
|
||||
Note about fast-forwards
|
||||
------------------------
|
||||
|
||||
When an update changes a branch (or more in general, a ref) that used to
|
||||
point at commit A to point at another commit B, it is called a
|
||||
fast-forward update if and only if B is a descendant of A.
|
||||
|
||||
In a fast-forward update from A to B, the set of commits that the original
|
||||
commit A built on top of is a subset of the commits the new commit B
|
||||
builds on top of. Hence, it does not lose any history.
|
||||
|
||||
In contrast, a non-fast-forward update will lose history. For example,
|
||||
suppose you and somebody else started at the same commit X, and you built
|
||||
a history leading to commit B while the other person built a history
|
||||
leading to commit A. The history looks like this:
|
||||
|
||||
----------------
|
||||
|
||||
B
|
||||
/
|
||||
---X---A
|
||||
|
||||
----------------
|
||||
|
||||
Further suppose that the other person already pushed changes leading to A
|
||||
back to the original repository you two obtained the original commit X.
|
||||
|
||||
The push done by the other person updated the branch that used to point at
|
||||
commit X to point at commit A. It is a fast-forward.
|
||||
|
||||
But if you try to push, you will attempt to update the branch (that
|
||||
now points at A) with commit B. This does _not_ fast-forward. If you did
|
||||
so, the changes introduced by commit A will be lost, because everybody
|
||||
will now start building on top of B.
|
||||
|
||||
The command by default does not allow an update that is not a fast-forward
|
||||
to prevent such loss of history.
|
||||
|
||||
If you do not want to lose your work (history from X to B) nor the work by
|
||||
the other person (history from X to A), you would need to first fetch the
|
||||
history from the repository, create a history that contains changes done
|
||||
by both parties, and push the result back.
|
||||
|
||||
You can perform "git pull", resolve potential conflicts, and "git push"
|
||||
the result. A "git pull" will create a merge commit C between commits A
|
||||
and B.
|
||||
|
||||
----------------
|
||||
|
||||
B---C
|
||||
/ /
|
||||
---X---A
|
||||
|
||||
----------------
|
||||
|
||||
Updating A with the resulting merge commit will fast-forward and your
|
||||
push will be accepted.
|
||||
|
||||
Alternatively, you can rebase your change between X and B on top of A,
|
||||
with "git pull --rebase", and push the result back. The rebase will
|
||||
create a new commit D that builds the change between X and B on top of
|
||||
A.
|
||||
|
||||
----------------
|
||||
|
||||
B D
|
||||
/ /
|
||||
---X---A
|
||||
|
||||
----------------
|
||||
|
||||
Again, updating A with this commit will fast-forward and your push will be
|
||||
accepted.
|
||||
|
||||
There is another common situation where you may encounter non-fast-forward
|
||||
rejection when you try to push, and it is possible even when you are
|
||||
pushing into a repository nobody else pushes into. After you push commit
|
||||
A yourself (in the first picture in this section), replace it with "git
|
||||
commit --amend" to produce commit B, and you try to push it out, because
|
||||
forgot that you have pushed A out already. In such a case, and only if
|
||||
you are certain that nobody in the meantime fetched your earlier commit A
|
||||
(and started building on top of it), you can run "git push --force" to
|
||||
overwrite it. In other words, "git push --force" is a method reserved for
|
||||
a case where you do mean to lose history.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ git-read-tree - Reads tree information into the index
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git read-tree' (<tree-ish> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
|
||||
'git read-tree' [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>]
|
||||
[-u [--exclude-per-directory=<gitignore>] | -i]]
|
||||
[--index-output=<file>]
|
||||
<tree-ish1> [<tree-ish2> [<tree-ish3>]]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@@ -114,14 +114,14 @@ These stale branches have already been removed from the remote repository
|
||||
referenced by <name>, but are still locally available in
|
||||
"remotes/<name>".
|
||||
+
|
||||
With `--dry-run` option, report what branches will be pruned, but do no
|
||||
With `--dry-run` option, report what branches will be pruned, but do not
|
||||
actually prune them.
|
||||
|
||||
'update'::
|
||||
|
||||
Fetch updates for a named set of remotes in the repository as defined by
|
||||
remotes.<group>. If a named group is not specified on the command line,
|
||||
the configuration parameter remotes.default will get used; if
|
||||
the configuration parameter remotes.default will be used; if
|
||||
remotes.default is not defined, all remotes which do not have the
|
||||
configuration parameter remote.<name>.skipDefaultUpdate set to true will
|
||||
be updated. (See linkgit:git-config[1]).
|
||||
|
||||
@@ -51,20 +51,26 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
Lists commit objects in reverse chronological order starting at the
|
||||
given commit(s), taking ancestry relationship into account. This is
|
||||
useful to produce human-readable log output.
|
||||
List commits that are reachable by following the `parent` links from the
|
||||
given commit(s), but exclude commits that are reachable from the one(s)
|
||||
given with a '{caret}' in front of them. The output is given in reverse
|
||||
chronological order by default.
|
||||
|
||||
Commits which are stated with a preceding '{caret}' cause listing to
|
||||
stop at that point. Their parents are implied. Thus the following
|
||||
command:
|
||||
You can think of this as a set operation. Commits given on the command
|
||||
line form a set of commits that are reachable from any of them, and then
|
||||
commits reachable from any of the ones given with '{caret}' in front are
|
||||
subtracted from that set. The remaining commits are what comes out in the
|
||||
command's output. Various other options and paths parameters can be used
|
||||
to further limit the result.
|
||||
|
||||
Thus, the following command:
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
$ git rev-list foo bar ^baz
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
means "list all the commits which are included in 'foo' and 'bar', but
|
||||
not in 'baz'".
|
||||
means "list all the commits which are reachable from 'foo' or 'bar', but
|
||||
not from 'baz'".
|
||||
|
||||
A special notation "'<commit1>'..'<commit2>'" can be used as a
|
||||
short-hand for "{caret}'<commit1>' '<commit2>'". For example, either of
|
||||
@@ -84,7 +90,7 @@ between the two operands. The following two commands are equivalent:
|
||||
$ git rev-list A...B
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
'git-rev-list' is a very essential git program, since it
|
||||
'rev-list' is a very essential git command, since it
|
||||
provides the ability to build and traverse commit ancestry graphs. For
|
||||
this reason, it has a lot of different options that enables it to be
|
||||
used by commands as different as 'git-bisect' and
|
||||
|
||||
@@ -142,8 +142,9 @@ user is prompted for a password while the input is masked for privacy.
|
||||
|
||||
--smtp-server-port=<port>::
|
||||
Specifies a port different from the default port (SMTP
|
||||
servers typically listen to smtp port 25 and ssmtp port
|
||||
465); symbolic port names (e.g. "submission" instead of 465)
|
||||
servers typically listen to smtp port 25, but may also listen to
|
||||
submission port 587, or the common SSL smtp port 465);
|
||||
symbolic port names (e.g. "submission" instead of 587)
|
||||
are also accepted. The port can also be set with the
|
||||
'sendemail.smtpserverport' configuration variable.
|
||||
|
||||
|
||||
@@ -8,11 +8,12 @@ git-show-branch - Show branches and their commits
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git show-branch' [--all] [--remotes] [--topo-order | --date-order]
|
||||
[--current] [--color | --no-color]
|
||||
'git show-branch' [-a|--all] [-r|--remotes] [--topo-order | --date-order]
|
||||
[--current] [--color | --no-color] [--sparse]
|
||||
[--more=<n> | --list | --independent | --merge-base]
|
||||
[--no-name | --sha1-name] [--topics]
|
||||
[<rev> | <glob>]...
|
||||
|
||||
'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
|
||||
|
||||
DESCRIPTION
|
||||
@@ -81,9 +82,11 @@ OPTIONS
|
||||
Synonym to `--more=-1`
|
||||
|
||||
--merge-base::
|
||||
Instead of showing the commit list, just act like the
|
||||
'git-merge-base -a' command, except that it can accept
|
||||
more than two heads.
|
||||
Instead of showing the commit list, determine possible
|
||||
merge bases for the specified commits. All merge bases
|
||||
will be contained in all specified commits. This is
|
||||
different from how linkgit:git-merge-base[1] handles
|
||||
the case of three or more commits.
|
||||
|
||||
--independent::
|
||||
Among the <reference>s given, display only the ones that
|
||||
|
||||
@@ -114,7 +114,8 @@ no conflicts.
|
||||
|
||||
clear::
|
||||
Remove all the stashed states. Note that those states will then
|
||||
be subject to pruning, and may be difficult or impossible to recover.
|
||||
be subject to pruning, and may be impossible to recover (see
|
||||
'Examples' below for a possible strategy).
|
||||
|
||||
drop [-q|--quiet] [<stash>]::
|
||||
|
||||
@@ -217,6 +218,20 @@ $ edit/build/test remaining parts
|
||||
$ git commit foo -m 'Remaining parts'
|
||||
----------------------------------------------------------------
|
||||
|
||||
Recovering stashes that were cleared/dropped erroneously::
|
||||
|
||||
If you mistakenly drop or clear stashes, they cannot be recovered
|
||||
through the normal safety mechanisms. However, you can try the
|
||||
following incantation to get a list of stashes that are still in your
|
||||
repository, but not reachable any more:
|
||||
+
|
||||
----------------------------------------------------------------
|
||||
git fsck --unreachable |
|
||||
grep commit | cut -d\ -f3 |
|
||||
xargs git log --merges --no-walk --grep=WIP
|
||||
----------------------------------------------------------------
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-checkout[1],
|
||||
|
||||
@@ -14,8 +14,8 @@ SYNOPSIS
|
||||
'git submodule' [--quiet] status [--cached] [--] [<path>...]
|
||||
'git submodule' [--quiet] init [--] [<path>...]
|
||||
'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
|
||||
[--reference <repository>] [--] [<path>...]
|
||||
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
|
||||
[--reference <repository>] [--merge] [--] [<path>...]
|
||||
'git submodule' [--quiet] summary [--cached] [--summary-limit <n>] [commit] [--] [<path>...]
|
||||
'git submodule' [--quiet] foreach <command>
|
||||
'git submodule' [--quiet] sync [--] [<path>...]
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ DESCRIPTION
|
||||
Given one argument, reads which branch head the given symbolic
|
||||
ref refers to and outputs its path, relative to the `.git/`
|
||||
directory. Typically you would give `HEAD` as the <name>
|
||||
argument to see on which branch your working tree is on.
|
||||
argument to see which branch your working tree is on.
|
||||
|
||||
Give two arguments, create or update a symbolic ref <name> to
|
||||
Given two arguments, creates or updates a symbolic ref <name> to
|
||||
point at the given branch <ref>.
|
||||
|
||||
A symbolic ref is a regular file that stores a string that
|
||||
|
||||
@@ -17,7 +17,10 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Adds a 'tag' reference in `.git/refs/tags/`
|
||||
|
||||
Adds a 'tag' reference in `.git/refs/tags/`. The tag <name> must pass
|
||||
linkgit:git-check-ref-format[1] which basicly means that control characters,
|
||||
space, ~, ^, :, ?, *, [ and \ are prohibited.
|
||||
|
||||
Unless `-f` is given, the tag must not yet exist in
|
||||
`.git/refs/tags/` directory.
|
||||
|
||||
@@ -8,7 +8,7 @@ git-verify-pack - Validate packed git archive files
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git verify-pack' [-v] [--] <pack>.idx ...
|
||||
'git verify-pack' [-v|--verbose] [--] <pack>.idx ...
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
@@ -23,6 +23,7 @@ OPTIONS
|
||||
The idx files to verify.
|
||||
|
||||
-v::
|
||||
--verbose::
|
||||
After verifying the pack, show list of objects contained
|
||||
in the pack.
|
||||
\--::
|
||||
|
||||
@@ -327,7 +327,7 @@ Synching repositories
|
||||
|
||||
include::cmds-synchingrepositories.txt[]
|
||||
|
||||
The following are helper programs used by the above; end users
|
||||
The following are helper commands used by the above; end users
|
||||
typically do not use them directly.
|
||||
|
||||
include::cmds-synchelpers.txt[]
|
||||
|
||||
@@ -404,7 +404,7 @@ Performing a three-way merge
|
||||
|
||||
The attribute `merge` affects how three versions of a file is
|
||||
merged when a file-level merge is necessary during `git merge`,
|
||||
and other programs such as `git revert` and `git cherry-pick`.
|
||||
and other commands such as `git revert` and `git cherry-pick`.
|
||||
|
||||
Set::
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ git *
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
This tutorial explains how to use the "core" git programs to set up and
|
||||
This tutorial explains how to use the "core" git commands to set up and
|
||||
work with a git repository.
|
||||
|
||||
If you just need to use git as a revision control system you may prefer
|
||||
@@ -1328,7 +1328,7 @@ into it later. Obviously, this repository creation needs to be
|
||||
done only once.
|
||||
|
||||
[NOTE]
|
||||
'git-push' uses a pair of programs,
|
||||
'git-push' uses a pair of commands,
|
||||
'git-send-pack' on your local machine, and 'git-receive-pack'
|
||||
on the remote machine. The communication between the two over
|
||||
the network internally uses an SSH connection.
|
||||
|
||||
675
Documentation/pt_BR/gittutorial.txt
Normal file
675
Documentation/pt_BR/gittutorial.txt
Normal file
@@ -0,0 +1,675 @@
|
||||
gittutorial(7)
|
||||
==============
|
||||
|
||||
NAME
|
||||
----
|
||||
gittutorial - Um tutorial de introdução ao git (para versão 1.5.1 ou mais nova)
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
git *
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
Este tutorial explica como importar um novo projeto para o git,
|
||||
adicionar mudanças a ele, e compartilhar mudanças com outros
|
||||
desenvolvedores.
|
||||
|
||||
Se, ao invés disso, você está interessado primariamente em usar git para
|
||||
obter um projeto, por exemplo, para testar a última versão, você pode
|
||||
preferir começar com os primeiros dois capítulos de
|
||||
link:user-manual.html[O Manual do Usuário Git].
|
||||
|
||||
Primeiro, note que você pode obter documentação para um comando como
|
||||
`git log --graph` com:
|
||||
|
||||
------------------------------------------------
|
||||
$ man git-log
|
||||
------------------------------------------------
|
||||
|
||||
ou:
|
||||
|
||||
------------------------------------------------
|
||||
$ git help log
|
||||
------------------------------------------------
|
||||
|
||||
Com a última forma, você pode usar o visualizador de manual de sua
|
||||
escolha; veja linkgit:git-help[1] para maior informação.
|
||||
|
||||
É uma boa idéia informar ao git seu nome e endereço público de email
|
||||
antes de fazer qualquer operação. A maneira mais fácil de fazê-lo é:
|
||||
|
||||
------------------------------------------------
|
||||
$ git config --global user.name "Seu Nome Vem Aqui"
|
||||
$ git config --global user.email voce@seudominio.exemplo.com
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
Importando um novo projeto
|
||||
-----------------------
|
||||
|
||||
Assuma que você tem um tarball project.tar.gz com seu trabalho inicial.
|
||||
Você pode colocá-lo sob controle de revisão git da seguinte forma:
|
||||
|
||||
------------------------------------------------
|
||||
$ tar xzf project.tar.gz
|
||||
$ cd project
|
||||
$ git init
|
||||
------------------------------------------------
|
||||
|
||||
Git irá responder
|
||||
|
||||
------------------------------------------------
|
||||
Initialized empty Git repository in .git/
|
||||
------------------------------------------------
|
||||
|
||||
Você agora iniciou seu diretório de trabalho--você deve ter notado um
|
||||
novo diretório criado, com o nome de ".git".
|
||||
|
||||
A seguir, diga ao git para gravar um instantâneo do conteúdo de todos os
|
||||
arquivos sob o diretório corrente (note o '.'), com 'git-add':
|
||||
|
||||
------------------------------------------------
|
||||
$ git add .
|
||||
------------------------------------------------
|
||||
|
||||
Este instantâneo está agora armazenado em uma área temporária que o git
|
||||
chama de "index" ou índice. Você pode armazenar permanentemente o
|
||||
conteúdo do índice no repositório com 'git-commit':
|
||||
|
||||
------------------------------------------------
|
||||
$ git commit
|
||||
------------------------------------------------
|
||||
|
||||
Isto vai te pedir por uma mensagem de commit. Você agora gravou sua
|
||||
primeira versão de seu projeto no git.
|
||||
|
||||
Fazendo mudanças
|
||||
--------------
|
||||
|
||||
Modifique alguns arquivos, e, então, adicione seu conteúdo atualizado ao
|
||||
índice:
|
||||
|
||||
------------------------------------------------
|
||||
$ git add file1 file2 file3
|
||||
------------------------------------------------
|
||||
|
||||
Você está agora pronto para fazer o commit. Você pode ver o que está
|
||||
para ser gravado usando 'git-diff' com a opção --cached:
|
||||
|
||||
------------------------------------------------
|
||||
$ git diff --cached
|
||||
------------------------------------------------
|
||||
|
||||
(Sem --cached, o comando 'git-diff' irá te mostrar quaisquer mudanças
|
||||
que você tenha feito mas ainda não adicionou ao índice.) Você também
|
||||
pode obter um breve sumário da situação com 'git-status':
|
||||
|
||||
------------------------------------------------
|
||||
$ git status
|
||||
# On branch master
|
||||
# Changes to be committed:
|
||||
# (use "git reset HEAD <file>..." to unstage)
|
||||
#
|
||||
# modified: file1
|
||||
# modified: file2
|
||||
# modified: file3
|
||||
#
|
||||
------------------------------------------------
|
||||
|
||||
Se você precisar fazer qualquer outro ajuste, faça-o agora, e, então,
|
||||
adicione qualquer conteúdo modificado ao índice. Finalmente, grave suas
|
||||
mudanças com:
|
||||
|
||||
------------------------------------------------
|
||||
$ git commit
|
||||
------------------------------------------------
|
||||
|
||||
Isto irá novamente te pedir por uma mensagem descrevendo a mudança, e,
|
||||
então, gravar a nova versão do projeto.
|
||||
|
||||
Alternativamente, ao invés de executar 'git-add' antes, você pode usar
|
||||
|
||||
------------------------------------------------
|
||||
$ git commit -a
|
||||
------------------------------------------------
|
||||
|
||||
o que irá automaticamente notar quaisquer arquivos modificados (mas não
|
||||
novos), adicioná-los ao índices, e gravar, tudo em um único passo.
|
||||
|
||||
Uma nota em mensagens de commit: Apesar de não ser exigido, é uma boa
|
||||
idéia começar a mensagem com uma simples e curta (menos de 50
|
||||
caracteres) linha sumarizando a mudança, seguida de uma linha em branco
|
||||
e, então, uma descrição mais detalhada. Ferramentas que transformam
|
||||
commits em email, por exemplo, usam a primeira linha no campo de
|
||||
cabeçalho Subject: e o resto no corpo.
|
||||
|
||||
Git rastreia conteúdo, não arquivos
|
||||
----------------------------
|
||||
|
||||
Muitos sistemas de controle de revisão provêem um comando `add` que diz
|
||||
ao sistema para começar a rastrear mudanças em um novo arquivo. O
|
||||
comando `add` do git faz algo mais simples e mais poderoso: 'git-add' é
|
||||
usado tanto para arquivos novos e arquivos recentemente modificados, e
|
||||
em ambos os casos, ele tira o instantâneo dos arquivos dados e armazena
|
||||
o conteúdo no índice, pronto para inclusão do próximo commit.
|
||||
|
||||
Visualizando história do projeto
|
||||
-----------------------
|
||||
|
||||
Em qualquer ponto você pode visualizar a história das suas mudanças
|
||||
usando
|
||||
|
||||
------------------------------------------------
|
||||
$ git log
|
||||
------------------------------------------------
|
||||
|
||||
Se você também quer ver a diferença completa a cada passo, use
|
||||
|
||||
------------------------------------------------
|
||||
$ git log -p
|
||||
------------------------------------------------
|
||||
|
||||
Geralmente, uma visão geral da mudança é útil para ter a sensação de
|
||||
cada passo
|
||||
|
||||
------------------------------------------------
|
||||
$ git log --stat --summary
|
||||
------------------------------------------------
|
||||
|
||||
Gerenciando "branches"/ramos
|
||||
-----------------
|
||||
|
||||
Um simples repositório git pode manter múltiplos ramos de
|
||||
desenvolvimento. Para criar um novo ramo chamado "experimental", use
|
||||
|
||||
------------------------------------------------
|
||||
$ git branch experimental
|
||||
------------------------------------------------
|
||||
|
||||
Se você executar agora
|
||||
|
||||
------------------------------------------------
|
||||
$ git branch
|
||||
------------------------------------------------
|
||||
|
||||
você vai obter uma lista de todos os ramos existentes:
|
||||
|
||||
------------------------------------------------
|
||||
experimental
|
||||
* master
|
||||
------------------------------------------------
|
||||
|
||||
O ramo "experimental" é o que você acaba de criar, e o ramo "master" é o
|
||||
ramo padrão que foi criado pra você automaticamente. O asterisco marca
|
||||
o ramo em que você está atualmente; digite
|
||||
|
||||
------------------------------------------------
|
||||
$ git checkout experimental
|
||||
------------------------------------------------
|
||||
|
||||
para mudar para o ramo experimental. Agora edite um arquivo, grave a
|
||||
mudança, e mude de volta para o ramo master:
|
||||
|
||||
------------------------------------------------
|
||||
(edita arquivo)
|
||||
$ git commit -a
|
||||
$ git checkout master
|
||||
------------------------------------------------
|
||||
|
||||
Verifique que a mudança que você fez não está mais visível, já que ela
|
||||
foi feita no ramo experimental e você está de volta ao ramo master.
|
||||
|
||||
Você pode fazer uma mudança diferente no ramo master:
|
||||
|
||||
------------------------------------------------
|
||||
(edit file)
|
||||
$ git commit -a
|
||||
------------------------------------------------
|
||||
|
||||
neste ponto, os dois ramos divergiram, com diferentes mudanças feitas em
|
||||
cada um. Para unificar as mudanças feitas no experimental para o
|
||||
master, execute
|
||||
|
||||
------------------------------------------------
|
||||
$ git merge experimental
|
||||
------------------------------------------------
|
||||
|
||||
Se as mudanças não conflitarem, estará pronto. Se existirem conflitos,
|
||||
marcadores serão deixados nos arquivos problemáticos exibindo o
|
||||
conflito;
|
||||
|
||||
------------------------------------------------
|
||||
$ git diff
|
||||
------------------------------------------------
|
||||
|
||||
vai exibir isto. Após você editar os arquivos para resolver os
|
||||
conflitos,
|
||||
|
||||
------------------------------------------------
|
||||
$ git commit -a
|
||||
------------------------------------------------
|
||||
|
||||
irá gravar o resultado da unificação. Finalmente,
|
||||
|
||||
------------------------------------------------
|
||||
$ gitk
|
||||
------------------------------------------------
|
||||
|
||||
vai mostrar uma bela representação gráfica da história resultante.
|
||||
|
||||
Neste ponto você pode remover seu ramo experimental com
|
||||
|
||||
------------------------------------------------
|
||||
$ git branch -d experimental
|
||||
------------------------------------------------
|
||||
|
||||
Este comando garante que as mudanças no ramo experimental já estão no
|
||||
ramo atual.
|
||||
|
||||
Se você desenvolve em um ramo ideia-louca, e se arrepende, você pode
|
||||
sempre remover o ramo com
|
||||
|
||||
-------------------------------------
|
||||
$ git branch -D ideia-louca
|
||||
-------------------------------------
|
||||
|
||||
Ramos são baratos e fáceis, então isto é uma boa maneira de experimentar
|
||||
alguma coisa.
|
||||
|
||||
Usando git para colaboração
|
||||
---------------------------
|
||||
|
||||
Suponha que Alice começou um novo projeto com um repositório git em
|
||||
/home/alice/project, e que Bob, que tem um diretório home na mesma
|
||||
máquina, quer contribuir.
|
||||
|
||||
Bob começa com:
|
||||
|
||||
------------------------------------------------
|
||||
bob$ git clone /home/alice/project myrepo
|
||||
------------------------------------------------
|
||||
|
||||
Isso cria um novo diretório "myrepo" contendo um clone do repositório de
|
||||
Alice. O clone está no mesmo pé que o projeto original, possuindo sua
|
||||
própria cópia da história do projeto original.
|
||||
|
||||
Bob então faz algumas mudanças e as grava:
|
||||
|
||||
------------------------------------------------
|
||||
(editar arquivos)
|
||||
bob$ git commit -a
|
||||
(repetir conforme necessário)
|
||||
------------------------------------------------
|
||||
|
||||
Quanto está pronto, ele diz a Alice para puxar as mudanças do
|
||||
repositório em /home/bob/myrepo. Ela o faz com:
|
||||
|
||||
------------------------------------------------
|
||||
alice$ cd /home/alice/project
|
||||
alice$ git pull /home/bob/myrepo master
|
||||
------------------------------------------------
|
||||
|
||||
Isto unifica as mudanças do ramo "master" do Bob ao ramo atual de Alice.
|
||||
Se Alice fez suas próprias mudanças no intervalo, ela, então, pode
|
||||
precisar corrigir manualmente quaisquer conflitos. (Note que o argumento
|
||||
"master" no comando acima é, de fato, desnecessário, já que é o padrão.)
|
||||
|
||||
O comando "pull" executa, então, duas operações: ele obtém mudanças de
|
||||
um ramo remoto, e, então, as unifica no ramo atual.
|
||||
|
||||
Note que, em geral, Alice gostaria que suas mudanças locais fossem
|
||||
gravadas antes de iniciar este "pull". Se o trabalho de Bob conflita
|
||||
com o que Alice fez desde que suas histórias se ramificaram, Alice irá
|
||||
usar seu diretório de trabalho e o índice para resolver conflitos, e
|
||||
mudanças locais existentes irão interferir com o processo de resolução
|
||||
de conflitos (git ainda irá realizar a obtenção mas irá se recusar a
|
||||
unificar --- Alice terá que se livrar de suas mudanças locais de alguma
|
||||
forma e puxar de novo quando isso acontecer).
|
||||
|
||||
Alice pode espiar o que Bob fez sem unificar primeiro, usando o comando
|
||||
"fetch"; isto permite Alice inspecionar o que Bob fez, usando um símbolo
|
||||
especial "FETCH_HEAD", com o fim de determinar se ele tem alguma coisa
|
||||
que vale puxar, assim:
|
||||
|
||||
------------------------------------------------
|
||||
alice$ git fetch /home/bob/myrepo master
|
||||
alice$ git log -p HEAD..FETCH_HEAD
|
||||
------------------------------------------------
|
||||
|
||||
Esta operação é segura mesmo se Alice tem mudanças locais não gravadas.
|
||||
A notação de intervalo "HEAD..FETCH_HEAD" significa mostrar tudo que é
|
||||
alcançável de FETCH_HEAD mas exclua tudo o que é alcançável de HEAD.
|
||||
Alice já sabe tudo que leva a seu estado atual (HEAD), e revisa o que Bob
|
||||
tem em seu estado (FETCH_HEAD) que ela ainda não viu com esse comando.
|
||||
|
||||
Se Alice quer visualizar o que Bob fez desde que suas histórias se
|
||||
ramificaram, ela pode disparar o seguinte comando:
|
||||
|
||||
------------------------------------------------
|
||||
$ gitk HEAD..FETCH_HEAD
|
||||
------------------------------------------------
|
||||
|
||||
Isto usa a mesma notação de intervalo que vimos antes com 'git log'.
|
||||
|
||||
Alice pode querer ver o que ambos fizeram desde que ramificaram. Ela
|
||||
pode usar a forma com três pontos ao invés da forma com dois pontos:
|
||||
|
||||
------------------------------------------------
|
||||
$ gitk HEAD...FETCH_HEAD
|
||||
------------------------------------------------
|
||||
|
||||
Isto significa "mostre tudo que é alcançável de qualquer um deles, mas
|
||||
exclua tudo que é alcançável a partir de ambos".
|
||||
|
||||
Por favor, note que essas notações de intervalo podem ser usadas tanto
|
||||
com gitk quanto com "git log".
|
||||
|
||||
Após inspecionar o que Bob fez, se não há nada urgente, Alice pode
|
||||
decidir continuar trabalhando sem puxar de Bob. Se a história de Bob
|
||||
tem alguma coisa que Alice precisa imediatamente, Alice pode optar por
|
||||
separar seu trabalho em progresso primeiro, fazer um "pull", e, então,
|
||||
finalmente, retomar seu trabalho em progresso em cima da história
|
||||
resultante.
|
||||
|
||||
Quando você está trabalhando em um pequeno grupo unido, não é incomum
|
||||
interagir com o mesmo repositório várias e várias vezes. Definindo um
|
||||
repositório remoto antes de tudo, você pode fazê-lo mais facilmente:
|
||||
|
||||
------------------------------------------------
|
||||
alice$ git remote add bob /home/bob/myrepo
|
||||
------------------------------------------------
|
||||
|
||||
Com isso, Alice pode executar a primeira parte da operação "pull" usando
|
||||
o comando 'git-fetch' sem unificar suas mudanças com seu próprio ramo,
|
||||
usando:
|
||||
|
||||
-------------------------------------
|
||||
alice$ git fetch bob
|
||||
-------------------------------------
|
||||
|
||||
Diferente da forma longa, quando Alice obteve de Bob usando um
|
||||
repositório remoto antes definido com 'git-remote', o que foi obtido é
|
||||
armazenado em um ramo remoto, neste caso `bob/master`. Então, após isso:
|
||||
|
||||
-------------------------------------
|
||||
alice$ git log -p master..bob/master
|
||||
-------------------------------------
|
||||
|
||||
mostra uma lista de todas as mudanças que Bob fez desde que ramificou do
|
||||
ramo master de Alice.
|
||||
|
||||
Após examinar essas mudanças, Alice pode unificá-las em seu ramo master:
|
||||
|
||||
-------------------------------------
|
||||
alice$ git merge bob/master
|
||||
-------------------------------------
|
||||
|
||||
Esse `merge` pode também ser feito puxando de seu próprio ramo remoto,
|
||||
assim:
|
||||
|
||||
-------------------------------------
|
||||
alice$ git pull . remotes/bob/master
|
||||
-------------------------------------
|
||||
|
||||
Note que 'git pull' sempre unifica ao ramo atual, independente do que
|
||||
mais foi passado na linha de comando.
|
||||
|
||||
Depois, Bob pode atualizar seu repositório com as últimas mudanças de
|
||||
Alice, usando
|
||||
|
||||
-------------------------------------
|
||||
bob$ git pull
|
||||
-------------------------------------
|
||||
|
||||
Note que ele não precisa dar o caminho do repositório de Alice; quando
|
||||
Bob clonou seu repositório, o git armazenou a localização de seu
|
||||
repositório na configuração do mesmo, e essa localização é usada
|
||||
para puxar:
|
||||
|
||||
-------------------------------------
|
||||
bob$ git config --get remote.origin.url
|
||||
/home/alice/project
|
||||
-------------------------------------
|
||||
|
||||
(A configuração completa criada por 'git-clone' é visível usando `git
|
||||
config -l`, e a página de manual linkgit:git-config[1] explica o
|
||||
significado de cada opção.)
|
||||
|
||||
Git também mantém uma cópia limpa do ramo master de Alice sob o nome
|
||||
"origin/master":
|
||||
|
||||
-------------------------------------
|
||||
bob$ git branch -r
|
||||
origin/master
|
||||
-------------------------------------
|
||||
|
||||
Se Bob decidir depois em trabalhar em um host diferente, ele ainda pode
|
||||
executar clones e puxar usando o protocolo ssh:
|
||||
|
||||
-------------------------------------
|
||||
bob$ git clone alice.org:/home/alice/project myrepo
|
||||
-------------------------------------
|
||||
|
||||
Alternativamente, o git tem um protocolo nativo, ou pode usar rsync ou
|
||||
http; veja linkgit:git-pull[1] para detalhes.
|
||||
|
||||
Git pode também ser usado em um modo parecido com CVS, com um
|
||||
repositório central para o qual vários usuários empurram modificações;
|
||||
veja linkgit:git-push[1] e linkgit:gitcvs-migration[7].
|
||||
|
||||
Explorando história
|
||||
-----------------
|
||||
|
||||
A história no git é representada como uma série de commits
|
||||
interrelacionados. Nós já vimos que o comando 'git-log' pode listar
|
||||
esses commits. Note que a primeira linha de cada entrada no log também
|
||||
dá o nome para o commit:
|
||||
|
||||
-------------------------------------
|
||||
$ git log
|
||||
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
|
||||
Author: Junio C Hamano <junkio@cox.net>
|
||||
Date: Tue May 16 17:18:22 2006 -0700
|
||||
|
||||
merge-base: Clarify the comments on post processing.
|
||||
-------------------------------------
|
||||
|
||||
Nós podemos dar este nome ao 'git-show' para ver os detalhes sobre este
|
||||
commit.
|
||||
|
||||
-------------------------------------
|
||||
$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
|
||||
-------------------------------------
|
||||
|
||||
Mas há outras formas de se referir aos commits. Você pode usar qualquer
|
||||
parte inicial do nome que seja longo o bastante para identificar
|
||||
unicamente o commit:
|
||||
|
||||
-------------------------------------
|
||||
$ git show c82a22c39c # os primeiros caracteres do nome são o bastante
|
||||
# usualmente
|
||||
$ git show HEAD # a ponta do ramo atual
|
||||
$ git show experimental # a ponta do ramo "experimental"
|
||||
-------------------------------------
|
||||
|
||||
Todo commit normalmente tem um commit "pai" que aponta para o estado
|
||||
anterior do projeto:
|
||||
|
||||
-------------------------------------
|
||||
$ git show HEAD^ # para ver o pai de HEAD
|
||||
$ git show HEAD^^ # para ver o avô de HEAD
|
||||
$ git show HEAD~4 # para ver o trisavô de HEAD
|
||||
-------------------------------------
|
||||
|
||||
Note que commits de unificação podem ter mais de um pai:
|
||||
|
||||
-------------------------------------
|
||||
$ git show HEAD^1 # mostra o primeiro pai de HEAD (o mesmo que HEAD^)
|
||||
$ git show HEAD^2 # mostra o segundo pai de HEAD
|
||||
-------------------------------------
|
||||
|
||||
Você também pode dar aos commits nomes à sua escolha; após executar
|
||||
|
||||
-------------------------------------
|
||||
$ git tag v2.5 1b2e1d63ff
|
||||
-------------------------------------
|
||||
|
||||
você pode se referir a 1b2e1d63ff pelo nome "v2.5". Se você pretende
|
||||
compartilhar esse nome com outras pessoas (por exemplo, para identificar
|
||||
uma versão de lançamento), você deveria criar um objeto "tag", e talvez
|
||||
assiná-lo; veja linkgit:git-tag[1] para detalhes.
|
||||
|
||||
Qualquer comando git que precise conhecer um commit pode receber
|
||||
quaisquer desses nomes. Por exemplo:
|
||||
|
||||
-------------------------------------
|
||||
$ git diff v2.5 HEAD # compara o HEAD atual com v2.5
|
||||
$ git branch stable v2.5 # inicia um novo ramo chamado "stable" baseado
|
||||
# em v2.5
|
||||
$ git reset --hard HEAD^ # reseta seu ramo atual e seu diretório de
|
||||
# trabalho a seu estado em HEAD^
|
||||
-------------------------------------
|
||||
|
||||
Seja cuidadoso com o último comando: além de perder quaisquer mudanças
|
||||
em seu diretório de trabalho, ele também remove todos os commits
|
||||
posteriores desse ramo. Se esse ramo é o único ramo contendo esses
|
||||
commits, eles serão perdidos. Também, não use 'git-reset' num ramo
|
||||
publicamente visível de onde outros desenvolvedores puxam, já que vai
|
||||
forçar unificações desnecessárias para que outros desenvolvedores limpem
|
||||
a história. Se você precisa desfazer mudanças que você empurrou, use
|
||||
'git-revert' no lugar.
|
||||
|
||||
O comando 'git-grep' pode buscar strings em qualquer versão de seu
|
||||
projeto, então
|
||||
|
||||
-------------------------------------
|
||||
$ git grep "hello" v2.5
|
||||
-------------------------------------
|
||||
|
||||
procura por todas as ocorrências de "hello" em v2.5.
|
||||
|
||||
Se você deixar de fora o nome do commit, 'git-grep' irá procurar
|
||||
quaisquer dos arquivos que ele gerencia no diretório corrente. Então
|
||||
|
||||
-------------------------------------
|
||||
$ git grep "hello"
|
||||
-------------------------------------
|
||||
|
||||
é uma forma rápida de buscar somente os arquivos que são rastreados pelo
|
||||
git.
|
||||
|
||||
Muitos comandos git também recebem um conjunto de commits, o que pode
|
||||
ser especificado de várias formas. Aqui estão alguns exemplos com 'git-log':
|
||||
|
||||
-------------------------------------
|
||||
$ git log v2.5..v2.6 # commits entre v2.5 e v2.6
|
||||
$ git log v2.5.. # commits desde v2.5
|
||||
$ git log --since="2 weeks ago" # commits das últimas 2 semanas
|
||||
$ git log v2.5.. Makefile # commits desde v2.5 que modificam
|
||||
# Makefile
|
||||
-------------------------------------
|
||||
|
||||
Você também pode dar ao 'git-log' um "intervalo" de commits onde o
|
||||
primeiro não é necessariamente um ancestral do segundo; por exemplo, se
|
||||
as pontas dos ramos "stable" e "master" divergiram de um commit
|
||||
comum algum tempo atrás, então
|
||||
|
||||
-------------------------------------
|
||||
$ git log stable..master
|
||||
-------------------------------------
|
||||
|
||||
irá listar os commits feitos no ramo "master" mas não no ramo
|
||||
"stable", enquanto
|
||||
|
||||
-------------------------------------
|
||||
$ git log master..stable
|
||||
-------------------------------------
|
||||
|
||||
irá listar a lista de commits feitos no ramo "stable" mas não no ramo
|
||||
"master".
|
||||
|
||||
O comando 'git-log' tem uma fraqueza: ele precisa mostrar os commits em
|
||||
uma lista. Quando a história tem linhas de desenvolvimento que
|
||||
divergiram e então foram unificadas novamente, a ordem em que 'git-log'
|
||||
apresenta essas mudanças é irrelevante.
|
||||
|
||||
A maioria dos projetos com múltiplos contribuidores (como o kernel
|
||||
Linux, ou o próprio git) tem unificações frequentes, e 'gitk' faz um
|
||||
trabalho melhor de visualizar sua história. Por exemplo,
|
||||
|
||||
-------------------------------------
|
||||
$ gitk --since="2 weeks ago" drivers/
|
||||
-------------------------------------
|
||||
|
||||
permite a você navegar em quaisquer commits desde as últimas duas semanas
|
||||
de commits que modificaram arquivos sob o diretório "drivers". (Nota:
|
||||
você pode ajustar as fontes do gitk segurando a tecla control enquanto
|
||||
pressiona "-" ou "+".)
|
||||
|
||||
Finalmente, a maioria dos comandos que recebem nomes de arquivo permitirão
|
||||
também, opcionalmente, preceder qualquer nome de arquivo por um
|
||||
commit, para especificar uma versão particular do arquivo:
|
||||
|
||||
-------------------------------------
|
||||
$ git diff v2.5:Makefile HEAD:Makefile.in
|
||||
-------------------------------------
|
||||
|
||||
Você pode usar 'git-show' para ver tal arquivo:
|
||||
|
||||
-------------------------------------
|
||||
$ git show v2.5:Makefile
|
||||
-------------------------------------
|
||||
|
||||
Próximos passos
|
||||
----------
|
||||
|
||||
Este tutorial deve ser o bastante para operar controle de revisão
|
||||
distribuído básico para seus projetos. No entanto, para entender
|
||||
plenamente a profundidade e o poder do git você precisa entender duas
|
||||
idéias simples nas quais ele se baseia:
|
||||
|
||||
* A base de objetos é um sistema bem elegante usado para armazenar a
|
||||
história de seu projeto--arquivos, diretórios, e commits.
|
||||
|
||||
* O arquivo de índice é um cache do estado de uma árvore de diretório,
|
||||
usado para criar commits, restaurar diretórios de trabalho, e
|
||||
armazenar as várias árvores envolvidas em uma unificação.
|
||||
|
||||
A parte dois deste tutorial explica a base de objetos, o arquivo de
|
||||
índice, e algumas outras coisinhas que você vai precisar pra usar o
|
||||
máximo do git. Você pode encontrá-la em linkgit:gittutorial-2[7].
|
||||
|
||||
Se você não quiser continuar com o tutorial agora nesse momento, algumas
|
||||
outras digressões que podem ser interessantes neste ponto são:
|
||||
|
||||
* linkgit:git-format-patch[1], linkgit:git-am[1]: Estes convertem
|
||||
séries de commits em patches para email, e vice-versa, úteis para
|
||||
projetos como o kernel Linux que dependem fortemente de patches
|
||||
enviados por email.
|
||||
|
||||
* linkgit:git-bisect[1]: Quando há uma regressão em seu projeto, uma
|
||||
forma de rastrear um bug é procurando pela história para encontrar o
|
||||
commit culpado. Git bisect pode ajudar a executar uma busca binária
|
||||
por esse commit. Ele é inteligente o bastante para executar uma
|
||||
busca próxima da ótima mesmo no caso de uma história complexa
|
||||
não-linear com muitos ramos unificados.
|
||||
|
||||
* link:everyday.html[GIT diariamente com 20 e tantos comandos]
|
||||
|
||||
* linkgit:gitcvs-migration[7]: Git para usuários de CVS.
|
||||
|
||||
VEJA TAMBÉM
|
||||
--------
|
||||
linkgit:gittutorial-2[7],
|
||||
linkgit:gitcvs-migration[7],
|
||||
linkgit:gitcore-tutorial[7],
|
||||
linkgit:gitglossary[7],
|
||||
linkgit:git-help[1],
|
||||
link:everyday.html[git diariamente],
|
||||
link:user-manual.html[O Manual do Usuário git]
|
||||
|
||||
GIT
|
||||
---
|
||||
Parte da suite linkgit:git[1].
|
||||
@@ -35,12 +35,32 @@ Functions
|
||||
Convenience functions that encapsulate a sequence of
|
||||
start_command() followed by finish_command(). The argument argv
|
||||
specifies the program and its arguments. The argument opt is zero
|
||||
or more of the flags `RUN_COMMAND_NO_STDIN`, `RUN_GIT_CMD`, or
|
||||
`RUN_COMMAND_STDOUT_TO_STDERR` that correspond to the members
|
||||
.no_stdin, .git_cmd, .stdout_to_stderr of `struct child_process`.
|
||||
or more of the flags `RUN_COMMAND_NO_STDIN`, `RUN_GIT_CMD`,
|
||||
`RUN_COMMAND_STDOUT_TO_STDERR`, or `RUN_SILENT_EXEC_FAILURE`
|
||||
that correspond to the members .no_stdin, .git_cmd,
|
||||
.stdout_to_stderr, .silent_exec_failure of `struct child_process`.
|
||||
The argument dir corresponds the member .dir. The argument env
|
||||
corresponds to the member .env.
|
||||
|
||||
The functions above do the following:
|
||||
|
||||
. If a system call failed, errno is set and -1 is returned. A diagnostic
|
||||
is printed.
|
||||
|
||||
. If the program was not found, then -1 is returned and errno is set to
|
||||
ENOENT; a diagnostic is printed only if .silent_exec_failure is 0.
|
||||
|
||||
. Otherwise, the program is run. If it terminates regularly, its exit
|
||||
code is returned. No diagnistic is printed, even if the exit code is
|
||||
non-zero.
|
||||
|
||||
. If the program terminated due to a signal, then the return value is the
|
||||
signal number - 128, ie. it is negative and so indicates an unusual
|
||||
condition; a diagnostic is printed. This return value can be passed to
|
||||
exit(2), which will report the same code to the parent process that a
|
||||
POSIX shell's $? would report for a program that died from the signal.
|
||||
|
||||
|
||||
`start_async`::
|
||||
|
||||
Run a function asynchronously. Takes a pointer to a `struct
|
||||
@@ -143,6 +163,11 @@ string pointers (NULL terminated) in .env:
|
||||
To specify a new initial working directory for the sub-process,
|
||||
specify it in the .dir member.
|
||||
|
||||
If the program cannot be found, the functions return -1 and set
|
||||
errno to ENOENT. Normally, an error message is printed, but if
|
||||
.silent_exec_failure is set to 1, no message is printed for this
|
||||
special error condition.
|
||||
|
||||
|
||||
* `struct async`
|
||||
|
||||
|
||||
@@ -1,12 +1,145 @@
|
||||
tree walking API
|
||||
================
|
||||
|
||||
Talk about <tree-walk.h>, things like
|
||||
The tree walking API is used to traverse and inspect trees.
|
||||
|
||||
* struct tree_desc
|
||||
* init_tree_desc
|
||||
* tree_entry_extract
|
||||
* update_tree_entry
|
||||
* get_tree_entry
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
(JC, Linus)
|
||||
`struct name_entry`::
|
||||
|
||||
An entry in a tree. Each entry has a sha1 identifier, pathname, and
|
||||
mode.
|
||||
|
||||
`struct tree_desc`::
|
||||
|
||||
A semi-opaque data structure used to maintain the current state of the
|
||||
walk.
|
||||
+
|
||||
* `buffer` is a pointer into the memory representation of the tree. It always
|
||||
points at the current entry being visited.
|
||||
|
||||
* `size` counts the number of bytes left in the `buffer`.
|
||||
|
||||
* `entry` points to the current entry being visited.
|
||||
|
||||
`struct traverse_info`::
|
||||
|
||||
A structure used to maintain the state of a traversal.
|
||||
+
|
||||
* `prev` points to the traverse_info which was used to descend into the
|
||||
current tree. If this is the top-level tree `prev` will point to
|
||||
a dummy traverse_info.
|
||||
|
||||
* `name` is the entry for the current tree (if the tree is a subtree).
|
||||
|
||||
* `pathlen` is the length of the full path for the current tree.
|
||||
|
||||
* `conflicts` can be used by callbacks to maintain directory-file conflicts.
|
||||
|
||||
* `fn` is a callback called for each entry in the tree. See Traversing for more
|
||||
information.
|
||||
|
||||
* `data` can be anything the `fn` callback would want to use.
|
||||
|
||||
Initializing
|
||||
------------
|
||||
|
||||
`init_tree_desc`::
|
||||
|
||||
Initialize a `tree_desc` and decode its first entry. The buffer and
|
||||
size parameters are assumed to be the same as the buffer and size
|
||||
members of `struct tree`.
|
||||
|
||||
`fill_tree_descriptor`::
|
||||
|
||||
Initialize a `tree_desc` and decode its first entry given the sha1 of
|
||||
a tree. Returns the `buffer` member if the sha1 is a valid tree
|
||||
identifier and NULL otherwise.
|
||||
|
||||
`setup_traverse_info`::
|
||||
|
||||
Initialize a `traverse_info` given the pathname of the tree to start
|
||||
traversing from. The `base` argument is assumed to be the `path`
|
||||
member of the `name_entry` being recursed into unless the tree is a
|
||||
top-level tree in which case the empty string ("") is used.
|
||||
|
||||
Walking
|
||||
-------
|
||||
|
||||
`tree_entry`::
|
||||
|
||||
Visit the next entry in a tree. Returns 1 when there are more entries
|
||||
left to visit and 0 when all entries have been visited. This is
|
||||
commonly used in the test of a while loop.
|
||||
|
||||
`tree_entry_len`::
|
||||
|
||||
Calculate the length of a tree entry's pathname. This utilizes the
|
||||
memory structure of a tree entry to avoid the overhead of using a
|
||||
generic strlen().
|
||||
|
||||
`update_tree_entry`::
|
||||
|
||||
Walk to the next entry in a tree. This is commonly used in conjunction
|
||||
with `tree_entry_extract` to inspect the current entry.
|
||||
|
||||
`tree_entry_extract`::
|
||||
|
||||
Decode the entry currently being visited (the one pointed to by
|
||||
`tree_desc's` `entry` member) and return the sha1 of the entry. The
|
||||
`pathp` and `modep` arguments are set to the entry's pathname and mode
|
||||
respectively.
|
||||
|
||||
`get_tree_entry`::
|
||||
|
||||
Find an entry in a tree given a pathname and the sha1 of a tree to
|
||||
search. Returns 0 if the entry is found and -1 otherwise. The third
|
||||
and fourth parameters are set to the entry's sha1 and mode
|
||||
respectively.
|
||||
|
||||
Traversing
|
||||
----------
|
||||
|
||||
`traverse_trees`::
|
||||
|
||||
Traverse `n` number of trees in parallel. The `fn` callback member of
|
||||
`traverse_info` is called once for each tree entry.
|
||||
|
||||
`traverse_callback_t`::
|
||||
The arguments passed to the traverse callback are as follows:
|
||||
+
|
||||
* `n` counts the number of trees being traversed.
|
||||
|
||||
* `mask` has its nth bit set if something exists in the nth entry.
|
||||
|
||||
* `dirmask` has its nth bit set if the nth tree's entry is a directory.
|
||||
|
||||
* `entry` is an array of size `n` where the nth entry is from the nth tree.
|
||||
|
||||
* `info` maintains the state of the traversal.
|
||||
|
||||
+
|
||||
Returning a negative value will terminate the traversal. Otherwise the
|
||||
return value is treated as an update mask. If the nth bit is set the nth tree
|
||||
will be updated and if the bit is not set the nth tree entry will be the
|
||||
same in the next callback invocation.
|
||||
|
||||
`make_traverse_path`::
|
||||
|
||||
Generate the full pathname of a tree entry based from the root of the
|
||||
traversal. For example, if the traversal has recursed into another
|
||||
tree named "bar" the pathname of an entry "baz" in the "bar"
|
||||
tree would be "bar/baz".
|
||||
|
||||
`traverse_path_len`::
|
||||
|
||||
Calculate the length of a pathname returned by `make_traverse_path`.
|
||||
This utilizes the memory structure of a tree entry to avoid the
|
||||
overhead of using a generic strlen().
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
Written by Junio C Hamano <gitster@pobox.com> and Linus Torvalds
|
||||
<torvalds@linux-foundation.org>
|
||||
|
||||
@@ -4131,7 +4131,7 @@ What does this mean?
|
||||
|
||||
`git rev-list` is the original version of the revision walker, which
|
||||
_always_ printed a list of revisions to stdout. It is still functional,
|
||||
and needs to, since most new Git programs start out as scripts using
|
||||
and needs to, since most new Git commands start out as scripts using
|
||||
`git rev-list`.
|
||||
|
||||
`git rev-parse` is not as important any more; it was only used to filter out
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.6.4
|
||||
DEF_VER=v1.6.4.GIT
|
||||
|
||||
LF='
|
||||
'
|
||||
|
||||
9
Makefile
9
Makefile
@@ -84,6 +84,10 @@ all::
|
||||
# specify your own (or DarwinPort's) include directories and
|
||||
# library directories by defining CFLAGS and LDFLAGS appropriately.
|
||||
#
|
||||
# Define BLK_SHA1 environment variable if you want the C version
|
||||
# of the SHA1 that assumes you can do unaligned 32-bit loads and
|
||||
# have a fast htonl() function.
|
||||
#
|
||||
# Define PPC_SHA1 environment variable when running make to make use of
|
||||
# a bundled SHA1 routine optimized for PowerPC.
|
||||
#
|
||||
@@ -1167,6 +1171,10 @@ ifdef NO_DEFLATE_BOUND
|
||||
BASIC_CFLAGS += -DNO_DEFLATE_BOUND
|
||||
endif
|
||||
|
||||
ifdef BLK_SHA1
|
||||
SHA1_HEADER = "block-sha1/sha1.h"
|
||||
LIB_OBJS += block-sha1/sha1.o
|
||||
else
|
||||
ifdef PPC_SHA1
|
||||
SHA1_HEADER = "ppc/sha1.h"
|
||||
LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
|
||||
@@ -1184,6 +1192,7 @@ else
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifdef NO_PERL_MAKEMAKER
|
||||
export NO_PERL_MAKEMAKER
|
||||
endif
|
||||
|
||||
280
block-sha1/sha1.c
Normal file
280
block-sha1/sha1.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Based on the Mozilla SHA1 (see mozilla-sha1/sha1.c),
|
||||
* optimized to do word accesses rather than byte accesses,
|
||||
* and to avoid unnecessary copies into the context array.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
/*
|
||||
* Force usage of rol or ror by selecting the one with the smaller constant.
|
||||
* It _can_ generate slightly smaller code (a constant of 1 is special), but
|
||||
* perhaps more importantly it's possibly faster on any uarch that does a
|
||||
* rotate with a loop.
|
||||
*/
|
||||
|
||||
#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
|
||||
#define SHA_ROL(x,n) SHA_ASM("rol", x, n)
|
||||
#define SHA_ROR(x,n) SHA_ASM("ror", x, n)
|
||||
|
||||
#else
|
||||
|
||||
#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r)))
|
||||
#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n))
|
||||
#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If you have 32 registers or more, the compiler can (and should)
|
||||
* try to change the array[] accesses into registers. However, on
|
||||
* machines with less than ~25 registers, that won't really work,
|
||||
* and at least gcc will make an unholy mess of it.
|
||||
*
|
||||
* So to avoid that mess which just slows things down, we force
|
||||
* the stores to memory to actually happen (we might be better off
|
||||
* with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
|
||||
* suggested by Artur Skawina - that will also make gcc unable to
|
||||
* try to do the silly "optimize away loads" part because it won't
|
||||
* see what the value will be).
|
||||
*
|
||||
* Ben Herrenschmidt reports that on PPC, the C version comes close
|
||||
* to the optimized asm with this (ie on PPC you don't want that
|
||||
* 'volatile', since there are lots of registers).
|
||||
*
|
||||
* On ARM we get the best code generation by forcing a full memory barrier
|
||||
* between each SHA_ROUND, otherwise gcc happily get wild with spilling and
|
||||
* the stack frame size simply explode and performance goes down the drain.
|
||||
*/
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define setW(x, val) (*(volatile unsigned int *)&W(x) = (val))
|
||||
#elif defined(__arm__)
|
||||
#define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
|
||||
#else
|
||||
#define setW(x, val) (W(x) = (val))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Performance might be improved if the CPU architecture is OK with
|
||||
* unaligned 32-bit loads and a fast ntohl() is available.
|
||||
* Otherwise fall back to byte loads and shifts which is portable,
|
||||
* and is faster on architectures with memory alignment issues.
|
||||
*/
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || \
|
||||
defined(__ppc__) || defined(__ppc64__) || \
|
||||
defined(__powerpc__) || defined(__powerpc64__) || \
|
||||
defined(__s390__) || defined(__s390x__)
|
||||
|
||||
#define get_be32(p) ntohl(*(unsigned int *)(p))
|
||||
#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define get_be32(p) ( \
|
||||
(*((unsigned char *)(p) + 0) << 24) | \
|
||||
(*((unsigned char *)(p) + 1) << 16) | \
|
||||
(*((unsigned char *)(p) + 2) << 8) | \
|
||||
(*((unsigned char *)(p) + 3) << 0) )
|
||||
#define put_be32(p, v) do { \
|
||||
unsigned int __v = (v); \
|
||||
*((unsigned char *)(p) + 0) = __v >> 24; \
|
||||
*((unsigned char *)(p) + 1) = __v >> 16; \
|
||||
*((unsigned char *)(p) + 2) = __v >> 8; \
|
||||
*((unsigned char *)(p) + 3) = __v >> 0; } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
/* This "rolls" over the 512-bit array */
|
||||
#define W(x) (array[(x)&15])
|
||||
|
||||
/*
|
||||
* Where do we get the source from? The first 16 iterations get it from
|
||||
* the input data, the next mix it from the 512-bit array.
|
||||
*/
|
||||
#define SHA_SRC(t) get_be32(data + t)
|
||||
#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
|
||||
|
||||
#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
|
||||
unsigned int TEMP = input(t); setW(t, TEMP); \
|
||||
E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \
|
||||
B = SHA_ROR(B, 2); } while (0)
|
||||
|
||||
#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
|
||||
#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
|
||||
#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
|
||||
#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
|
||||
#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E )
|
||||
|
||||
static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data)
|
||||
{
|
||||
unsigned int A,B,C,D,E;
|
||||
unsigned int array[16];
|
||||
|
||||
A = ctx->H[0];
|
||||
B = ctx->H[1];
|
||||
C = ctx->H[2];
|
||||
D = ctx->H[3];
|
||||
E = ctx->H[4];
|
||||
|
||||
/* Round 1 - iterations 0-16 take their input from 'data' */
|
||||
T_0_15( 0, A, B, C, D, E);
|
||||
T_0_15( 1, E, A, B, C, D);
|
||||
T_0_15( 2, D, E, A, B, C);
|
||||
T_0_15( 3, C, D, E, A, B);
|
||||
T_0_15( 4, B, C, D, E, A);
|
||||
T_0_15( 5, A, B, C, D, E);
|
||||
T_0_15( 6, E, A, B, C, D);
|
||||
T_0_15( 7, D, E, A, B, C);
|
||||
T_0_15( 8, C, D, E, A, B);
|
||||
T_0_15( 9, B, C, D, E, A);
|
||||
T_0_15(10, A, B, C, D, E);
|
||||
T_0_15(11, E, A, B, C, D);
|
||||
T_0_15(12, D, E, A, B, C);
|
||||
T_0_15(13, C, D, E, A, B);
|
||||
T_0_15(14, B, C, D, E, A);
|
||||
T_0_15(15, A, B, C, D, E);
|
||||
|
||||
/* Round 1 - tail. Input from 512-bit mixing array */
|
||||
T_16_19(16, E, A, B, C, D);
|
||||
T_16_19(17, D, E, A, B, C);
|
||||
T_16_19(18, C, D, E, A, B);
|
||||
T_16_19(19, B, C, D, E, A);
|
||||
|
||||
/* Round 2 */
|
||||
T_20_39(20, A, B, C, D, E);
|
||||
T_20_39(21, E, A, B, C, D);
|
||||
T_20_39(22, D, E, A, B, C);
|
||||
T_20_39(23, C, D, E, A, B);
|
||||
T_20_39(24, B, C, D, E, A);
|
||||
T_20_39(25, A, B, C, D, E);
|
||||
T_20_39(26, E, A, B, C, D);
|
||||
T_20_39(27, D, E, A, B, C);
|
||||
T_20_39(28, C, D, E, A, B);
|
||||
T_20_39(29, B, C, D, E, A);
|
||||
T_20_39(30, A, B, C, D, E);
|
||||
T_20_39(31, E, A, B, C, D);
|
||||
T_20_39(32, D, E, A, B, C);
|
||||
T_20_39(33, C, D, E, A, B);
|
||||
T_20_39(34, B, C, D, E, A);
|
||||
T_20_39(35, A, B, C, D, E);
|
||||
T_20_39(36, E, A, B, C, D);
|
||||
T_20_39(37, D, E, A, B, C);
|
||||
T_20_39(38, C, D, E, A, B);
|
||||
T_20_39(39, B, C, D, E, A);
|
||||
|
||||
/* Round 3 */
|
||||
T_40_59(40, A, B, C, D, E);
|
||||
T_40_59(41, E, A, B, C, D);
|
||||
T_40_59(42, D, E, A, B, C);
|
||||
T_40_59(43, C, D, E, A, B);
|
||||
T_40_59(44, B, C, D, E, A);
|
||||
T_40_59(45, A, B, C, D, E);
|
||||
T_40_59(46, E, A, B, C, D);
|
||||
T_40_59(47, D, E, A, B, C);
|
||||
T_40_59(48, C, D, E, A, B);
|
||||
T_40_59(49, B, C, D, E, A);
|
||||
T_40_59(50, A, B, C, D, E);
|
||||
T_40_59(51, E, A, B, C, D);
|
||||
T_40_59(52, D, E, A, B, C);
|
||||
T_40_59(53, C, D, E, A, B);
|
||||
T_40_59(54, B, C, D, E, A);
|
||||
T_40_59(55, A, B, C, D, E);
|
||||
T_40_59(56, E, A, B, C, D);
|
||||
T_40_59(57, D, E, A, B, C);
|
||||
T_40_59(58, C, D, E, A, B);
|
||||
T_40_59(59, B, C, D, E, A);
|
||||
|
||||
/* Round 4 */
|
||||
T_60_79(60, A, B, C, D, E);
|
||||
T_60_79(61, E, A, B, C, D);
|
||||
T_60_79(62, D, E, A, B, C);
|
||||
T_60_79(63, C, D, E, A, B);
|
||||
T_60_79(64, B, C, D, E, A);
|
||||
T_60_79(65, A, B, C, D, E);
|
||||
T_60_79(66, E, A, B, C, D);
|
||||
T_60_79(67, D, E, A, B, C);
|
||||
T_60_79(68, C, D, E, A, B);
|
||||
T_60_79(69, B, C, D, E, A);
|
||||
T_60_79(70, A, B, C, D, E);
|
||||
T_60_79(71, E, A, B, C, D);
|
||||
T_60_79(72, D, E, A, B, C);
|
||||
T_60_79(73, C, D, E, A, B);
|
||||
T_60_79(74, B, C, D, E, A);
|
||||
T_60_79(75, A, B, C, D, E);
|
||||
T_60_79(76, E, A, B, C, D);
|
||||
T_60_79(77, D, E, A, B, C);
|
||||
T_60_79(78, C, D, E, A, B);
|
||||
T_60_79(79, B, C, D, E, A);
|
||||
|
||||
ctx->H[0] += A;
|
||||
ctx->H[1] += B;
|
||||
ctx->H[2] += C;
|
||||
ctx->H[3] += D;
|
||||
ctx->H[4] += E;
|
||||
}
|
||||
|
||||
void blk_SHA1_Init(blk_SHA_CTX *ctx)
|
||||
{
|
||||
ctx->size = 0;
|
||||
|
||||
/* Initialize H with the magic constants (see FIPS180 for constants) */
|
||||
ctx->H[0] = 0x67452301;
|
||||
ctx->H[1] = 0xefcdab89;
|
||||
ctx->H[2] = 0x98badcfe;
|
||||
ctx->H[3] = 0x10325476;
|
||||
ctx->H[4] = 0xc3d2e1f0;
|
||||
}
|
||||
|
||||
void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len)
|
||||
{
|
||||
int lenW = ctx->size & 63;
|
||||
|
||||
ctx->size += len;
|
||||
|
||||
/* Read the data into W and process blocks as they get full */
|
||||
if (lenW) {
|
||||
int left = 64 - lenW;
|
||||
if (len < left)
|
||||
left = len;
|
||||
memcpy(lenW + (char *)ctx->W, data, left);
|
||||
lenW = (lenW + left) & 63;
|
||||
len -= left;
|
||||
data = ((const char *)data + left);
|
||||
if (lenW)
|
||||
return;
|
||||
blk_SHA1_Block(ctx, ctx->W);
|
||||
}
|
||||
while (len >= 64) {
|
||||
blk_SHA1_Block(ctx, data);
|
||||
data = ((const char *)data + 64);
|
||||
len -= 64;
|
||||
}
|
||||
if (len)
|
||||
memcpy(ctx->W, data, len);
|
||||
}
|
||||
|
||||
void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx)
|
||||
{
|
||||
static const unsigned char pad[64] = { 0x80 };
|
||||
unsigned int padlen[2];
|
||||
int i;
|
||||
|
||||
/* Pad with a binary 1 (ie 0x80), then zeroes, then length */
|
||||
padlen[0] = htonl(ctx->size >> 29);
|
||||
padlen[1] = htonl(ctx->size << 3);
|
||||
|
||||
i = ctx->size & 63;
|
||||
blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i)));
|
||||
blk_SHA1_Update(ctx, padlen, 8);
|
||||
|
||||
/* Output hash */
|
||||
for (i = 0; i < 5; i++)
|
||||
put_be32(hashout + i*4, ctx->H[i]);
|
||||
}
|
||||
20
block-sha1/sha1.h
Normal file
20
block-sha1/sha1.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Based on the Mozilla SHA1 (see mozilla-sha1/sha1.h),
|
||||
* optimized to do word accesses rather than byte accesses,
|
||||
* and to avoid unnecessary copies into the context array.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
unsigned int H[5];
|
||||
unsigned int W[16];
|
||||
unsigned long long size;
|
||||
} blk_SHA_CTX;
|
||||
|
||||
void blk_SHA1_Init(blk_SHA_CTX *ctx);
|
||||
void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len);
|
||||
void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
|
||||
|
||||
#define git_SHA_CTX blk_SHA_CTX
|
||||
#define git_SHA1_Init blk_SHA1_Init
|
||||
#define git_SHA1_Update blk_SHA1_Update
|
||||
#define git_SHA1_Final blk_SHA1_Final
|
||||
@@ -457,6 +457,76 @@ static int guess_p_value(const char *nameline)
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does the ---/+++ line has the POSIX timestamp after the last HT?
|
||||
* GNU diff puts epoch there to signal a creation/deletion event. Is
|
||||
* this such a timestamp?
|
||||
*/
|
||||
static int has_epoch_timestamp(const char *nameline)
|
||||
{
|
||||
/*
|
||||
* We are only interested in epoch timestamp; any non-zero
|
||||
* fraction cannot be one, hence "(\.0+)?" in the regexp below.
|
||||
* For the same reason, the date must be either 1969-12-31 or
|
||||
* 1970-01-01, and the seconds part must be "00".
|
||||
*/
|
||||
const char stamp_regexp[] =
|
||||
"^(1969-12-31|1970-01-01)"
|
||||
" "
|
||||
"[0-2][0-9]:[0-5][0-9]:00(\\.0+)?"
|
||||
" "
|
||||
"([-+][0-2][0-9][0-5][0-9])\n";
|
||||
const char *timestamp = NULL, *cp;
|
||||
static regex_t *stamp;
|
||||
regmatch_t m[10];
|
||||
int zoneoffset;
|
||||
int hourminute;
|
||||
int status;
|
||||
|
||||
for (cp = nameline; *cp != '\n'; cp++) {
|
||||
if (*cp == '\t')
|
||||
timestamp = cp + 1;
|
||||
}
|
||||
if (!timestamp)
|
||||
return 0;
|
||||
if (!stamp) {
|
||||
stamp = xmalloc(sizeof(*stamp));
|
||||
if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) {
|
||||
warning("Cannot prepare timestamp regexp %s",
|
||||
stamp_regexp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
status = regexec(stamp, timestamp, ARRAY_SIZE(m), m, 0);
|
||||
if (status) {
|
||||
if (status != REG_NOMATCH)
|
||||
warning("regexec returned %d for input: %s",
|
||||
status, timestamp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
zoneoffset = strtol(timestamp + m[3].rm_so + 1, NULL, 10);
|
||||
zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100);
|
||||
if (timestamp[m[3].rm_so] == '-')
|
||||
zoneoffset = -zoneoffset;
|
||||
|
||||
/*
|
||||
* YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
|
||||
* (west of GMT) or 1970-01-01 (east of GMT)
|
||||
*/
|
||||
if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) ||
|
||||
(0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10)))
|
||||
return 0;
|
||||
|
||||
hourminute = (strtol(timestamp + 11, NULL, 10) * 60 +
|
||||
strtol(timestamp + 14, NULL, 10) -
|
||||
zoneoffset);
|
||||
|
||||
return ((zoneoffset < 0 && hourminute == 1440) ||
|
||||
(0 <= zoneoffset && !hourminute));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the name etc info from the ---/+++ lines of a traditional patch header
|
||||
*
|
||||
@@ -493,7 +563,17 @@ static void parse_traditional_patch(const char *first, const char *second, struc
|
||||
} else {
|
||||
name = find_name(first, NULL, p_value, TERM_SPACE | TERM_TAB);
|
||||
name = find_name(second, name, p_value, TERM_SPACE | TERM_TAB);
|
||||
patch->old_name = patch->new_name = name;
|
||||
if (has_epoch_timestamp(first)) {
|
||||
patch->is_new = 1;
|
||||
patch->is_delete = 0;
|
||||
patch->new_name = name;
|
||||
} else if (has_epoch_timestamp(second)) {
|
||||
patch->is_new = 0;
|
||||
patch->is_delete = 1;
|
||||
patch->old_name = name;
|
||||
} else {
|
||||
patch->old_name = patch->new_name = name;
|
||||
}
|
||||
}
|
||||
if (!name)
|
||||
die("unable to find filename in patch at line %d", linenr);
|
||||
|
||||
@@ -31,6 +31,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
int i;
|
||||
int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0;
|
||||
int ignored_only = 0, baselen = 0, config_set = 0, errors = 0;
|
||||
int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
|
||||
struct strbuf directory = STRBUF_INIT;
|
||||
struct dir_struct dir;
|
||||
static const char **pathspec;
|
||||
@@ -69,6 +70,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
die("clean.requireForce%s set and -n or -f not given; "
|
||||
"refusing to clean", config_set ? "" : " not");
|
||||
|
||||
if (force > 1)
|
||||
rm_flags = 0;
|
||||
|
||||
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
|
||||
|
||||
if (!ignored)
|
||||
@@ -131,7 +135,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
(matches == MATCHED_EXACTLY)) {
|
||||
if (!quiet)
|
||||
printf("Removing %s\n", qname);
|
||||
if (remove_dir_recursively(&directory, 0) != 0) {
|
||||
if (remove_dir_recursively(&directory,
|
||||
rm_flags) != 0) {
|
||||
warning("failed to remove '%s'", qname);
|
||||
errors++;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ static int tags; /* Allow lightweight tags */
|
||||
static int longformat;
|
||||
static int abbrev = DEFAULT_ABBREV;
|
||||
static int max_candidates = 10;
|
||||
static int found_names;
|
||||
static const char *pattern;
|
||||
static int always;
|
||||
|
||||
@@ -49,6 +50,7 @@ static void add_to_known_names(const char *path,
|
||||
memcpy(e->path, path, len);
|
||||
commit->util = e;
|
||||
}
|
||||
found_names = 1;
|
||||
}
|
||||
|
||||
static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data)
|
||||
@@ -195,6 +197,9 @@ static void describe(const char *arg, int last_one)
|
||||
for_each_ref(get_name, NULL);
|
||||
}
|
||||
|
||||
if (!found_names)
|
||||
die("cannot describe '%s'", sha1_to_hex(sha1));
|
||||
|
||||
n = cmit->util;
|
||||
if (n) {
|
||||
/*
|
||||
|
||||
@@ -218,6 +218,8 @@ static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv
|
||||
revs->max_count = 3;
|
||||
else if (!strcmp(argv[1], "-q"))
|
||||
options |= DIFF_SILENT_ON_REMOVED;
|
||||
else if (!strcmp(argv[1], "-h"))
|
||||
usage(builtin_diff_usage);
|
||||
else
|
||||
return error("invalid option: %s", argv[1]);
|
||||
argv++; argc--;
|
||||
|
||||
@@ -26,6 +26,7 @@ static int progress;
|
||||
static enum { ABORT, VERBATIM, WARN, STRIP } signed_tag_mode = ABORT;
|
||||
static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ABORT;
|
||||
static int fake_missing_tagger;
|
||||
static int no_data;
|
||||
|
||||
static int parse_opt_signed_tag_mode(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
@@ -116,6 +117,9 @@ static void handle_object(const unsigned char *sha1)
|
||||
char *buf;
|
||||
struct object *object;
|
||||
|
||||
if (no_data)
|
||||
return;
|
||||
|
||||
if (is_null_sha1(sha1))
|
||||
return;
|
||||
|
||||
@@ -173,7 +177,7 @@ static void show_filemodify(struct diff_queue_struct *q,
|
||||
* Links refer to objects in another repositories;
|
||||
* output the SHA-1 verbatim.
|
||||
*/
|
||||
if (S_ISGITLINK(spec->mode))
|
||||
if (no_data || S_ISGITLINK(spec->mode))
|
||||
printf("M %06o %s %s\n", spec->mode,
|
||||
sha1_to_hex(spec->sha1), spec->path);
|
||||
else {
|
||||
@@ -580,6 +584,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||
"Import marks from this file"),
|
||||
OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
|
||||
"Fake a tagger when tags lack one"),
|
||||
{ OPTION_NEGBIT, 0, "data", &no_data, NULL,
|
||||
"Skip output of blob data",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 },
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
||||
@@ -52,26 +52,58 @@ static int grep_config(const char *var, const char *value, void *cb)
|
||||
return git_color_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return non-zero if max_depth is negative or path has no more then max_depth
|
||||
* slashes.
|
||||
*/
|
||||
static int accept_subdir(const char *path, int max_depth)
|
||||
{
|
||||
if (max_depth < 0)
|
||||
return 1;
|
||||
|
||||
while ((path = strchr(path, '/')) != NULL) {
|
||||
max_depth--;
|
||||
if (max_depth < 0)
|
||||
return 0;
|
||||
path++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return non-zero if name is a subdirectory of match and is not too deep.
|
||||
*/
|
||||
static int is_subdir(const char *name, int namelen,
|
||||
const char *match, int matchlen, int max_depth)
|
||||
{
|
||||
if (matchlen > namelen || strncmp(name, match, matchlen))
|
||||
return 0;
|
||||
|
||||
if (name[matchlen] == '\0') /* exact match */
|
||||
return 1;
|
||||
|
||||
if (!matchlen || match[matchlen-1] == '/' || name[matchlen] == '/')
|
||||
return accept_subdir(name + matchlen + 1, max_depth);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* git grep pathspecs are somewhat different from diff-tree pathspecs;
|
||||
* pathname wildcards are allowed.
|
||||
*/
|
||||
static int pathspec_matches(const char **paths, const char *name)
|
||||
static int pathspec_matches(const char **paths, const char *name, int max_depth)
|
||||
{
|
||||
int namelen, i;
|
||||
if (!paths || !*paths)
|
||||
return 1;
|
||||
return accept_subdir(name, max_depth);
|
||||
namelen = strlen(name);
|
||||
for (i = 0; paths[i]; i++) {
|
||||
const char *match = paths[i];
|
||||
int matchlen = strlen(match);
|
||||
const char *cp, *meta;
|
||||
|
||||
if (!matchlen ||
|
||||
((matchlen <= namelen) &&
|
||||
!strncmp(name, match, matchlen) &&
|
||||
(match[matchlen-1] == '/' ||
|
||||
name[matchlen] == '\0' || name[matchlen] == '/')))
|
||||
if (is_subdir(name, namelen, match, matchlen, max_depth))
|
||||
return 1;
|
||||
if (!fnmatch(match, name, 0))
|
||||
return 1;
|
||||
@@ -421,7 +453,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||
int kept;
|
||||
if (!S_ISREG(ce->ce_mode))
|
||||
continue;
|
||||
if (!pathspec_matches(paths, ce->name))
|
||||
if (!pathspec_matches(paths, ce->name, opt->max_depth))
|
||||
continue;
|
||||
name = ce->name;
|
||||
if (name[0] == '-') {
|
||||
@@ -478,7 +510,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
|
||||
struct cache_entry *ce = active_cache[nr];
|
||||
if (!S_ISREG(ce->ce_mode))
|
||||
continue;
|
||||
if (!pathspec_matches(paths, ce->name))
|
||||
if (!pathspec_matches(paths, ce->name, opt->max_depth))
|
||||
continue;
|
||||
/*
|
||||
* If CE_VALID is on, we assume worktree file and its cache entry
|
||||
@@ -538,7 +570,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
|
||||
strbuf_addch(&pathbuf, '/');
|
||||
|
||||
down = pathbuf.buf + tn_len;
|
||||
if (!pathspec_matches(paths, down))
|
||||
if (!pathspec_matches(paths, down, opt->max_depth))
|
||||
;
|
||||
else if (S_ISREG(entry.mode))
|
||||
hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
|
||||
@@ -692,6 +724,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
OPT_SET_INT('I', NULL, &opt.binary,
|
||||
"don't match patterns in binary files",
|
||||
GREP_BINARY_NOMATCH),
|
||||
{ OPTION_INTEGER, 0, "max-depth", &opt.max_depth, "depth",
|
||||
"descend at most <depth> levels", PARSE_OPT_NONEG,
|
||||
NULL, 1 },
|
||||
OPT_GROUP(""),
|
||||
OPT_BIT('E', "extended-regexp", &opt.regflags,
|
||||
"use extended POSIX regular expressions", REG_EXTENDED),
|
||||
@@ -768,6 +803,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
opt.pathname = 1;
|
||||
opt.pattern_tail = &opt.pattern_list;
|
||||
opt.regflags = REG_NEWLINE;
|
||||
opt.max_depth = -1;
|
||||
|
||||
strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD);
|
||||
opt.color = -1;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "cache.h"
|
||||
#include "builtin.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
#ifndef DEFAULT_GIT_TEMPLATE_DIR
|
||||
#define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
|
||||
@@ -370,8 +371,16 @@ static int guess_repository_type(const char *git_dir)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char init_db_usage[] =
|
||||
"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
|
||||
static int shared_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
*((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const init_db_usage[] = {
|
||||
"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [directory]",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* If you want to, you can share the DB area with any number of branches.
|
||||
@@ -384,25 +393,60 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
|
||||
const char *git_dir;
|
||||
const char *template_dir = NULL;
|
||||
unsigned int flags = 0;
|
||||
int i;
|
||||
const struct option init_db_options[] = {
|
||||
OPT_STRING(0, "template", &template_dir, "template-directory",
|
||||
"provide the directory from which templates will be used"),
|
||||
OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
|
||||
"create a bare repository", 1),
|
||||
{ OPTION_CALLBACK, 0, "shared", &init_shared_repository,
|
||||
"permissions",
|
||||
"specify that the git repository is to be shared amongst several users",
|
||||
PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
|
||||
OPT_BIT('q', "quiet", &flags, "be quiet", INIT_DB_QUIET),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++, argv++) {
|
||||
const char *arg = argv[1];
|
||||
if (!prefixcmp(arg, "--template="))
|
||||
template_dir = arg+11;
|
||||
else if (!strcmp(arg, "--bare")) {
|
||||
static char git_dir[PATH_MAX+1];
|
||||
is_bare_repository_cfg = 1;
|
||||
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
|
||||
sizeof(git_dir)), 0);
|
||||
} else if (!strcmp(arg, "--shared"))
|
||||
init_shared_repository = PERM_GROUP;
|
||||
else if (!prefixcmp(arg, "--shared="))
|
||||
init_shared_repository = git_config_perm("arg", arg+9);
|
||||
else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
|
||||
flags |= INIT_DB_QUIET;
|
||||
else
|
||||
usage(init_db_usage);
|
||||
argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
|
||||
|
||||
if (argc == 1) {
|
||||
int mkdir_tried = 0;
|
||||
retry:
|
||||
if (chdir(argv[0]) < 0) {
|
||||
if (!mkdir_tried) {
|
||||
int saved;
|
||||
/*
|
||||
* At this point we haven't read any configuration,
|
||||
* and we know shared_repository should always be 0;
|
||||
* but just in case we play safe.
|
||||
*/
|
||||
saved = shared_repository;
|
||||
shared_repository = 0;
|
||||
switch (safe_create_leading_directories_const(argv[0])) {
|
||||
case -3:
|
||||
errno = EEXIST;
|
||||
/* fallthru */
|
||||
case -1:
|
||||
die_errno("cannot mkdir %s", argv[0]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
shared_repository = saved;
|
||||
if (mkdir(argv[0], 0777) < 0)
|
||||
die_errno("cannot mkdir %s", argv[0]);
|
||||
mkdir_tried = 1;
|
||||
goto retry;
|
||||
}
|
||||
die_errno("cannot chdir to %s", argv[0]);
|
||||
}
|
||||
} else if (0 < argc) {
|
||||
usage(init_db_usage[0]);
|
||||
}
|
||||
if (is_bare_repository_cfg == 1) {
|
||||
static char git_dir[PATH_MAX+1];
|
||||
|
||||
setenv(GIT_DIR_ENVIRONMENT,
|
||||
getcwd(git_dir, sizeof(git_dir)), 0);
|
||||
}
|
||||
|
||||
if (init_shared_repository != -1)
|
||||
|
||||
@@ -27,6 +27,10 @@ static int default_show_root = 1;
|
||||
static const char *fmt_patch_subject_prefix = "PATCH";
|
||||
static const char *fmt_pretty;
|
||||
|
||||
static const char * const builtin_log_usage =
|
||||
"git log [<options>] [<since>..<until>] [[--] <path>...]\n"
|
||||
" or: git show [options] <object>...";
|
||||
|
||||
static void cmd_log_init(int argc, const char **argv, const char *prefix,
|
||||
struct rev_info *rev)
|
||||
{
|
||||
@@ -61,6 +65,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
|
||||
rev->show_decorations = 1;
|
||||
} else if (!strcmp(arg, "--source")) {
|
||||
rev->show_source = 1;
|
||||
} else if (!strcmp(arg, "-h")) {
|
||||
usage(builtin_log_usage);
|
||||
} else
|
||||
die("unrecognized argument: %s", arg);
|
||||
}
|
||||
@@ -257,7 +263,7 @@ static void show_tagger(char *buf, int len, struct rev_info *rev)
|
||||
pp_user_info("Tagger", rev->commit_format, &out, buf, rev->date_mode,
|
||||
git_log_output_encoding ?
|
||||
git_log_output_encoding: git_commit_encoding);
|
||||
printf("%s\n", out.buf);
|
||||
printf("%s", out.buf);
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
@@ -329,11 +335,14 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
||||
case OBJ_TAG: {
|
||||
struct tag *t = (struct tag *)o;
|
||||
|
||||
if (rev.shown_one)
|
||||
putchar('\n');
|
||||
printf("%stag %s%s\n",
|
||||
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
||||
t->tag,
|
||||
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
||||
ret = show_object(o->sha1, 1, &rev);
|
||||
rev.shown_one = 1;
|
||||
if (ret)
|
||||
break;
|
||||
o = parse_object(t->tagged->sha1);
|
||||
@@ -345,12 +354,15 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
||||
break;
|
||||
}
|
||||
case OBJ_TREE:
|
||||
if (rev.shown_one)
|
||||
putchar('\n');
|
||||
printf("%stree %s%s\n\n",
|
||||
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
|
||||
name,
|
||||
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
|
||||
read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
|
||||
show_tree_object, NULL);
|
||||
rev.shown_one = 1;
|
||||
break;
|
||||
case OBJ_COMMIT:
|
||||
rev.pending.nr = rev.pending.alloc = 0;
|
||||
@@ -658,6 +670,10 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
log_write_email_headers(rev, head, &subject_start, &extra_headers,
|
||||
&need_8bit_cte);
|
||||
|
||||
for (i = 0; !need_8bit_cte && i < nr; i++)
|
||||
if (has_non_ascii(list[i]->buffer))
|
||||
need_8bit_cte = 1;
|
||||
|
||||
msg = body;
|
||||
pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,
|
||||
encoding);
|
||||
|
||||
@@ -23,7 +23,7 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
|
||||
}
|
||||
|
||||
static const char * const merge_base_usage[] = {
|
||||
"git merge-base [--all] <commit-id> <commit-id>...",
|
||||
"git merge-base [-a|--all] <commit> <commit>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -358,6 +358,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct strbuf bname = STRBUF_INIT;
|
||||
const char *ptr;
|
||||
char *found_ref;
|
||||
int len, early;
|
||||
|
||||
strbuf_branchname(&bname, remote);
|
||||
@@ -368,14 +369,17 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
if (!remote_head)
|
||||
die("'%s' does not point to a commit", remote);
|
||||
|
||||
strbuf_addstr(&buf, "refs/heads/");
|
||||
strbuf_addstr(&buf, remote);
|
||||
resolve_ref(buf.buf, branch_head, 0, NULL);
|
||||
|
||||
if (!hashcmp(remote_head->sha1, branch_head)) {
|
||||
strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
|
||||
sha1_to_hex(branch_head), remote);
|
||||
goto cleanup;
|
||||
if (dwim_ref(remote, strlen(remote), branch_head, &found_ref) > 0) {
|
||||
if (!prefixcmp(found_ref, "refs/heads/")) {
|
||||
strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
|
||||
sha1_to_hex(branch_head), remote);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!prefixcmp(found_ref, "refs/remotes/")) {
|
||||
strbuf_addf(msg, "%s\t\tremote branch '%s' of .\n",
|
||||
sha1_to_hex(branch_head), remote);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if remote matches <name>^^^.. or <name>~<number> */
|
||||
@@ -594,7 +598,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
|
||||
discard_cache();
|
||||
if (read_cache() < 0)
|
||||
die("failed to read the cache");
|
||||
return -ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ static int pack_compression_level = Z_DEFAULT_COMPRESSION;
|
||||
static int pack_compression_seen;
|
||||
|
||||
static unsigned long delta_cache_size = 0;
|
||||
static unsigned long max_delta_cache_size = 0;
|
||||
static unsigned long max_delta_cache_size = 256 * 1024 * 1024;
|
||||
static unsigned long cache_max_small_delta_size = 1000;
|
||||
|
||||
static unsigned long window_memory_limit = 0;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "progress.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char prune_packed_usage[] =
|
||||
"git prune-packed [-n] [-q]";
|
||||
static const char * const prune_packed_usage[] = {
|
||||
"git prune-packed [-n|--dry-run] [-q|--quiet]",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define DRY_RUN 01
|
||||
#define VERBOSE 02
|
||||
@@ -68,24 +71,16 @@ void prune_packed_objects(int opts)
|
||||
|
||||
int cmd_prune_packed(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i;
|
||||
int opts = VERBOSE;
|
||||
const struct option prune_packed_options[] = {
|
||||
OPT_BIT('n', "dry-run", &opts, "dry run", DRY_RUN),
|
||||
OPT_NEGBIT('q', "quiet", &opts, "be quiet", VERBOSE),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
argc = parse_options(argc, argv, prefix, prune_packed_options,
|
||||
prune_packed_usage, 0);
|
||||
|
||||
if (*arg == '-') {
|
||||
if (!strcmp(arg, "-n"))
|
||||
opts |= DRY_RUN;
|
||||
else if (!strcmp(arg, "-q"))
|
||||
opts &= ~VERBOSE;
|
||||
else
|
||||
usage(prune_packed_usage);
|
||||
continue;
|
||||
}
|
||||
/* Handle arguments here .. */
|
||||
usage(prune_packed_usage);
|
||||
}
|
||||
prune_packed_objects(opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ static int do_push(const char *repo, int flags)
|
||||
struct transport *transport =
|
||||
transport_get(remote, url[i]);
|
||||
int err;
|
||||
int nonfastforward;
|
||||
if (receivepack)
|
||||
transport_set_option(transport,
|
||||
TRANS_OPT_RECEIVEPACK, receivepack);
|
||||
@@ -148,13 +149,19 @@ static int do_push(const char *repo, int flags)
|
||||
|
||||
if (flags & TRANSPORT_PUSH_VERBOSE)
|
||||
fprintf(stderr, "Pushing to %s\n", url[i]);
|
||||
err = transport_push(transport, refspec_nr, refspec, flags);
|
||||
err = transport_push(transport, refspec_nr, refspec, flags,
|
||||
&nonfastforward);
|
||||
err |= transport_disconnect(transport);
|
||||
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
error("failed to push some refs to '%s'", url[i]);
|
||||
if (nonfastforward) {
|
||||
printf("To prevent you from losing history, non-fast-forward updates were rejected.\n"
|
||||
"Merge the remote changes before pushing again.\n"
|
||||
"See 'non-fast forward' section of 'git push --help' for details.\n");
|
||||
}
|
||||
errs++;
|
||||
}
|
||||
return !!errs;
|
||||
@@ -168,6 +175,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
|
||||
const char *repo = NULL; /* default repository */
|
||||
|
||||
struct option options[] = {
|
||||
OPT_BIT('q', "quiet", &flags, "be quiet", TRANSPORT_PUSH_QUIET),
|
||||
OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE),
|
||||
OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
|
||||
OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "unpack-trees.h"
|
||||
#include "dir.h"
|
||||
#include "builtin.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static int nr_trees;
|
||||
static struct tree *trees[MAX_UNPACK_TREES];
|
||||
@@ -29,7 +30,39 @@ static int list_tree(unsigned char *sha1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char read_tree_usage[] = "git read-tree (<sha> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])";
|
||||
static const char * const read_tree_usage[] = {
|
||||
"git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int index_output_cb(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
set_alternate_index_output(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exclude_per_directory_cb(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct dir_struct *dir;
|
||||
struct unpack_trees_options *opts;
|
||||
|
||||
opts = (struct unpack_trees_options *)opt->value;
|
||||
|
||||
if (opts->dir)
|
||||
die("more than one --exclude-per-directory given.");
|
||||
|
||||
dir = xcalloc(1, sizeof(*opts->dir));
|
||||
dir->flags |= DIR_SHOW_IGNORED;
|
||||
dir->exclude_per_dir = arg;
|
||||
opts->dir = dir;
|
||||
/* We do not need to nor want to do read-directory
|
||||
* here; we are merely interested in reusing the
|
||||
* per directory ignore stack mechanism.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct lock_file lock_file;
|
||||
|
||||
@@ -39,6 +72,34 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
|
||||
unsigned char sha1[20];
|
||||
struct tree_desc t[MAX_UNPACK_TREES];
|
||||
struct unpack_trees_options opts;
|
||||
int prefix_set = 0;
|
||||
const struct option read_tree_options[] = {
|
||||
{ OPTION_CALLBACK, 0, "index-output", NULL, "FILE",
|
||||
"write resulting index to <FILE>",
|
||||
PARSE_OPT_NONEG, index_output_cb },
|
||||
OPT__VERBOSE(&opts.verbose_update),
|
||||
OPT_GROUP("Merging"),
|
||||
OPT_SET_INT('m', NULL, &opts.merge,
|
||||
"perform a merge in addition to a read", 1),
|
||||
OPT_SET_INT(0, "trivial", &opts.trivial_merges_only,
|
||||
"3-way merge if no file level merging required", 1),
|
||||
OPT_SET_INT(0, "aggressive", &opts.aggressive,
|
||||
"3-way merge in presence of adds and removes", 1),
|
||||
OPT_SET_INT(0, "reset", &opts.reset,
|
||||
"same as -m, but discard unmerged entries", 1),
|
||||
{ OPTION_STRING, 0, "prefix", &opts.prefix, "<subdirectory>/",
|
||||
"read the tree into the index under <subdirectory>/",
|
||||
PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP },
|
||||
OPT_SET_INT('u', NULL, &opts.update,
|
||||
"update working tree with merge result", 1),
|
||||
{ OPTION_CALLBACK, 0, "exclude-per-directory", &opts,
|
||||
"gitignore",
|
||||
"allow explicitly ignored files to be overwritten",
|
||||
PARSE_OPT_NONEG, exclude_per_directory_cb },
|
||||
OPT_SET_INT('i', NULL, &opts.index_only,
|
||||
"don't check the working tree after merging", 1),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.head_idx = -1;
|
||||
@@ -49,114 +110,31 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
|
||||
|
||||
newfd = hold_locked_index(&lock_file, 1);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
argc = parse_options(argc, argv, unused_prefix, read_tree_options,
|
||||
read_tree_usage, 0);
|
||||
|
||||
if (read_cache_unmerged() && (opts.prefix || opts.merge))
|
||||
die("You need to resolve your current index first");
|
||||
|
||||
prefix_set = opts.prefix ? 1 : 0;
|
||||
if (1 < opts.merge + opts.reset + prefix_set)
|
||||
die("Which one? -m, --reset, or --prefix?");
|
||||
stage = opts.merge = (opts.reset || opts.merge || prefix_set);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
/* "-u" means "update", meaning that a merge will update
|
||||
* the working tree.
|
||||
*/
|
||||
if (!strcmp(arg, "-u")) {
|
||||
opts.update = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(arg, "-v")) {
|
||||
opts.verbose_update = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* "-i" means "index only", meaning that a merge will
|
||||
* not even look at the working tree.
|
||||
*/
|
||||
if (!strcmp(arg, "-i")) {
|
||||
opts.index_only = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!prefixcmp(arg, "--index-output=")) {
|
||||
set_alternate_index_output(arg + 15);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* "--prefix=<subdirectory>/" means keep the current index
|
||||
* entries and put the entries from the tree under the
|
||||
* given subdirectory.
|
||||
*/
|
||||
if (!prefixcmp(arg, "--prefix=")) {
|
||||
if (stage || opts.merge || opts.prefix)
|
||||
usage(read_tree_usage);
|
||||
opts.prefix = arg + 9;
|
||||
opts.merge = 1;
|
||||
stage = 1;
|
||||
if (read_cache_unmerged())
|
||||
die("you need to resolve your current index first");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This differs from "-m" in that we'll silently ignore
|
||||
* unmerged entries and overwrite working tree files that
|
||||
* correspond to them.
|
||||
*/
|
||||
if (!strcmp(arg, "--reset")) {
|
||||
if (stage || opts.merge || opts.prefix)
|
||||
usage(read_tree_usage);
|
||||
opts.reset = 1;
|
||||
opts.merge = 1;
|
||||
stage = 1;
|
||||
read_cache_unmerged();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(arg, "--trivial")) {
|
||||
opts.trivial_merges_only = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(arg, "--aggressive")) {
|
||||
opts.aggressive = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* "-m" stands for "merge", meaning we start in stage 1 */
|
||||
if (!strcmp(arg, "-m")) {
|
||||
if (stage || opts.merge || opts.prefix)
|
||||
usage(read_tree_usage);
|
||||
if (read_cache_unmerged())
|
||||
die("you need to resolve your current index first");
|
||||
stage = 1;
|
||||
opts.merge = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!prefixcmp(arg, "--exclude-per-directory=")) {
|
||||
struct dir_struct *dir;
|
||||
|
||||
if (opts.dir)
|
||||
die("more than one --exclude-per-directory are given.");
|
||||
|
||||
dir = xcalloc(1, sizeof(*opts.dir));
|
||||
dir->flags |= DIR_SHOW_IGNORED;
|
||||
dir->exclude_per_dir = arg + 24;
|
||||
opts.dir = dir;
|
||||
/* We do not need to nor want to do read-directory
|
||||
* here; we are merely interested in reusing the
|
||||
* per directory ignore stack mechanism.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* using -u and -i at the same time makes no sense */
|
||||
if (1 < opts.index_only + opts.update)
|
||||
usage(read_tree_usage);
|
||||
|
||||
if (get_sha1(arg, sha1))
|
||||
die("Not a valid object name %s", arg);
|
||||
if (list_tree(sha1) < 0)
|
||||
die("failed to unpack tree object %s", arg);
|
||||
stage++;
|
||||
}
|
||||
if (1 < opts.index_only + opts.update)
|
||||
die("-u and -i at the same time makes no sense");
|
||||
if ((opts.update||opts.index_only) && !opts.merge)
|
||||
usage(read_tree_usage);
|
||||
die("%s is meaningless without -m, --reset, or --prefix",
|
||||
opts.update ? "-u" : "-i");
|
||||
if ((opts.dir && !opts.update))
|
||||
die("--exclude-per-directory is meaningless unless -u");
|
||||
if (opts.merge && !opts.index_only)
|
||||
|
||||
@@ -123,31 +123,6 @@ static struct command *commands;
|
||||
static const char pre_receive_hook[] = "hooks/pre-receive";
|
||||
static const char post_receive_hook[] = "hooks/post-receive";
|
||||
|
||||
static int run_status(int code, const char *cmd_name)
|
||||
{
|
||||
switch (code) {
|
||||
case 0:
|
||||
return 0;
|
||||
case -ERR_RUN_COMMAND_FORK:
|
||||
return error("fork of %s failed", cmd_name);
|
||||
case -ERR_RUN_COMMAND_EXEC:
|
||||
return error("execute of %s failed", cmd_name);
|
||||
case -ERR_RUN_COMMAND_PIPE:
|
||||
return error("pipe failed");
|
||||
case -ERR_RUN_COMMAND_WAITPID:
|
||||
return error("waitpid failed");
|
||||
case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
|
||||
return error("waitpid is confused");
|
||||
case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
|
||||
return error("%s died of signal", cmd_name);
|
||||
case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
|
||||
return error("%s died strangely", cmd_name);
|
||||
default:
|
||||
error("%s exited with error code %d", cmd_name, -code);
|
||||
return -code;
|
||||
}
|
||||
}
|
||||
|
||||
static int run_receive_hook(const char *hook_name)
|
||||
{
|
||||
static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
|
||||
@@ -174,7 +149,7 @@ static int run_receive_hook(const char *hook_name)
|
||||
|
||||
code = start_command(&proc);
|
||||
if (code)
|
||||
return run_status(code, hook_name);
|
||||
return code;
|
||||
for (cmd = commands; cmd; cmd = cmd->next) {
|
||||
if (!cmd->error_string) {
|
||||
size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
|
||||
@@ -186,7 +161,7 @@ static int run_receive_hook(const char *hook_name)
|
||||
}
|
||||
}
|
||||
close(proc.in);
|
||||
return run_status(finish_command(&proc), hook_name);
|
||||
return finish_command(&proc);
|
||||
}
|
||||
|
||||
static int run_update_hook(struct command *cmd)
|
||||
@@ -203,9 +178,8 @@ static int run_update_hook(struct command *cmd)
|
||||
argv[3] = sha1_to_hex(cmd->new_sha1);
|
||||
argv[4] = NULL;
|
||||
|
||||
return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
|
||||
RUN_COMMAND_STDOUT_TO_STDERR),
|
||||
update_hook);
|
||||
return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
|
||||
RUN_COMMAND_STDOUT_TO_STDERR);
|
||||
}
|
||||
|
||||
static int is_ref_checked_out(const char *ref)
|
||||
@@ -419,7 +393,6 @@ static void run_update_post_hook(struct command *cmd)
|
||||
argv[argc] = NULL;
|
||||
status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
|
||||
| RUN_COMMAND_STDOUT_TO_STDERR);
|
||||
run_status(status, update_post_hook);
|
||||
}
|
||||
|
||||
static void execute_commands(const char *unpacker_error)
|
||||
@@ -537,7 +510,6 @@ static const char *unpack(void)
|
||||
code = run_command_v_opt(unpacker, RUN_GIT_CMD);
|
||||
if (!code)
|
||||
return NULL;
|
||||
run_status(code, unpacker[0]);
|
||||
return "unpack-objects abnormal exit";
|
||||
} else {
|
||||
const char *keeper[7];
|
||||
@@ -563,7 +535,6 @@ static const char *unpack(void)
|
||||
ip.git_cmd = 1;
|
||||
status = start_command(&ip);
|
||||
if (status) {
|
||||
run_status(status, keeper[0]);
|
||||
return "index-pack fork failed";
|
||||
}
|
||||
pack_lockfile = index_pack_lockfile(ip.out);
|
||||
@@ -573,7 +544,6 @@ static const char *unpack(void)
|
||||
reprepare_packed_git();
|
||||
return NULL;
|
||||
}
|
||||
run_status(status, keeper[0]);
|
||||
return "index-pack abnormal exit";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,7 +694,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
|
||||
*/
|
||||
|
||||
static const char reflog_usage[] =
|
||||
"git reflog (expire | ...)";
|
||||
"git reflog [ show | expire | delete ]";
|
||||
|
||||
int cmd_reflog(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
|
||||
@@ -44,6 +44,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
struct child_process po;
|
||||
int i;
|
||||
@@ -53,6 +54,8 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
|
||||
argv[i++] = "--thin";
|
||||
if (args->use_ofs_delta)
|
||||
argv[i++] = "--delta-base-offset";
|
||||
if (args->quiet)
|
||||
argv[i++] = "-q";
|
||||
memset(&po, 0, sizeof(po));
|
||||
po.argv = argv;
|
||||
po.in = -1;
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char* show_branch_usage[] = {
|
||||
"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base] [--topics] [--color] [<refs>...]",
|
||||
"--reflog[=n[,b]] [--list] [--color] <branch>",
|
||||
"git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--color | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [<rev> | <glob>]...",
|
||||
"git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -665,7 +665,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
OPT_BOOLEAN(0, "sha1-name", &sha1_name,
|
||||
"name commits with their object names"),
|
||||
OPT_BOOLEAN(0, "merge-base", &merge_base,
|
||||
"act like git merge-base -a"),
|
||||
"show possible merge bases"),
|
||||
OPT_BOOLEAN(0, "independent", &independent,
|
||||
"show refs unreachable from any other ref"),
|
||||
OPT_BOOLEAN(0, "topo-order", &lifo,
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
#include "cache.h"
|
||||
#include "pack.h"
|
||||
#include "pack-revindex.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
#define MAX_CHAIN 50
|
||||
|
||||
static void show_pack_info(struct packed_git *p)
|
||||
{
|
||||
uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1];
|
||||
uint32_t nr_objects, i;
|
||||
int cnt;
|
||||
unsigned long chain_histogram[MAX_CHAIN+1], baseobjects;
|
||||
|
||||
nr_objects = p->num_objects;
|
||||
memset(chain_histogram, 0, sizeof(chain_histogram));
|
||||
baseobjects = 0;
|
||||
|
||||
for (i = 0; i < nr_objects; i++) {
|
||||
const unsigned char *sha1;
|
||||
@@ -29,9 +33,11 @@ static void show_pack_info(struct packed_git *p)
|
||||
&delta_chain_length,
|
||||
base_sha1);
|
||||
printf("%s ", sha1_to_hex(sha1));
|
||||
if (!delta_chain_length)
|
||||
if (!delta_chain_length) {
|
||||
printf("%-6s %lu %lu %"PRIuMAX"\n",
|
||||
type, size, store_size, (uintmax_t)offset);
|
||||
baseobjects++;
|
||||
}
|
||||
else {
|
||||
printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
|
||||
type, size, store_size, (uintmax_t)offset,
|
||||
@@ -43,15 +49,21 @@ static void show_pack_info(struct packed_git *p)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= MAX_CHAIN; i++) {
|
||||
if (!chain_histogram[i])
|
||||
if (baseobjects)
|
||||
printf("non delta: %lu object%s\n",
|
||||
baseobjects, baseobjects > 1 ? "s" : "");
|
||||
|
||||
for (cnt = 1; cnt <= MAX_CHAIN; cnt++) {
|
||||
if (!chain_histogram[cnt])
|
||||
continue;
|
||||
printf("chain length = %"PRIu32": %"PRIu32" object%s\n", i,
|
||||
chain_histogram[i], chain_histogram[i] > 1 ? "s" : "");
|
||||
printf("chain length = %d: %lu object%s\n", cnt,
|
||||
chain_histogram[cnt],
|
||||
chain_histogram[cnt] > 1 ? "s" : "");
|
||||
}
|
||||
if (chain_histogram[0])
|
||||
printf("chain length > %d: %"PRIu32" object%s\n", MAX_CHAIN,
|
||||
chain_histogram[0], chain_histogram[0] > 1 ? "s" : "");
|
||||
printf("chain length > %d: %lu object%s\n", MAX_CHAIN,
|
||||
chain_histogram[0],
|
||||
chain_histogram[0] > 1 ? "s" : "");
|
||||
}
|
||||
|
||||
static int verify_one_pack(const char *path, int verbose)
|
||||
@@ -107,36 +119,31 @@ static int verify_one_pack(const char *path, int verbose)
|
||||
return err;
|
||||
}
|
||||
|
||||
static const char verify_pack_usage[] = "git verify-pack [-v] <pack>...";
|
||||
static const char * const verify_pack_usage[] = {
|
||||
"git verify-pack [-v|--verbose] <pack>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
int cmd_verify_pack(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int err = 0;
|
||||
int verbose = 0;
|
||||
int no_more_options = 0;
|
||||
int nothing_done = 1;
|
||||
int i;
|
||||
const struct option verify_pack_options[] = {
|
||||
OPT__VERBOSE(&verbose),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
while (1 < argc) {
|
||||
if (!no_more_options && argv[1][0] == '-') {
|
||||
if (!strcmp("-v", argv[1]))
|
||||
verbose = 1;
|
||||
else if (!strcmp("--", argv[1]))
|
||||
no_more_options = 1;
|
||||
else
|
||||
usage(verify_pack_usage);
|
||||
}
|
||||
else {
|
||||
if (verify_one_pack(argv[1], verbose))
|
||||
err = 1;
|
||||
discard_revindex();
|
||||
nothing_done = 0;
|
||||
}
|
||||
argc--; argv++;
|
||||
argc = parse_options(argc, argv, prefix, verify_pack_options,
|
||||
verify_pack_usage, 0);
|
||||
if (argc < 1)
|
||||
usage_with_options(verify_pack_usage, verify_pack_options);
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (verify_one_pack(argv[i], verbose))
|
||||
err = 1;
|
||||
discard_revindex();
|
||||
}
|
||||
|
||||
if (nothing_done)
|
||||
usage(verify_pack_usage);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,12 @@
|
||||
#include "tag.h"
|
||||
#include "run-command.h"
|
||||
#include <signal.h>
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char builtin_verify_tag_usage[] =
|
||||
"git verify-tag [-v|--verbose] <tag>...";
|
||||
static const char * const verify_tag_usage[] = {
|
||||
"git verify-tag [-v|--verbose] <tag>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
|
||||
|
||||
@@ -89,17 +92,17 @@ static int verify_tag(const char *name, int verbose)
|
||||
int cmd_verify_tag(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i = 1, verbose = 0, had_error = 0;
|
||||
const struct option verify_tag_options[] = {
|
||||
OPT__VERBOSE(&verbose),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
if (argc > 1 &&
|
||||
(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose"))) {
|
||||
verbose = 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
argc = parse_options(argc, argv, prefix, verify_tag_options,
|
||||
verify_tag_usage, PARSE_OPT_KEEP_ARGV0);
|
||||
if (argc <= i)
|
||||
usage(builtin_verify_tag_usage);
|
||||
usage_with_options(verify_tag_usage, verify_tag_options);
|
||||
|
||||
/* sometimes the program was terminated because this signal
|
||||
* was received in the process of writing the gpg input: */
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
#include "cache.h"
|
||||
#include "tree.h"
|
||||
#include "cache-tree.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char write_tree_usage[] =
|
||||
"git write-tree [--missing-ok] [--prefix=<prefix>/]";
|
||||
static const char * const write_tree_usage[] = {
|
||||
"git write-tree [--missing-ok] [--prefix=<prefix>/]",
|
||||
NULL
|
||||
};
|
||||
|
||||
int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
|
||||
{
|
||||
@@ -17,27 +20,22 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
|
||||
const char *prefix = NULL;
|
||||
unsigned char sha1[20];
|
||||
const char *me = "git-write-tree";
|
||||
struct option write_tree_options[] = {
|
||||
OPT_BIT(0, "missing-ok", &flags, "allow missing objects",
|
||||
WRITE_TREE_MISSING_OK),
|
||||
{ OPTION_STRING, 0, "prefix", &prefix, "<prefix>/",
|
||||
"write tree object for a subdirectory <prefix>" ,
|
||||
PARSE_OPT_LITERAL_ARGHELP },
|
||||
{ OPTION_BIT, 0, "ignore-cache-tree", &flags, NULL,
|
||||
"only useful for debugging",
|
||||
PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, NULL,
|
||||
WRITE_TREE_IGNORE_CACHE_TREE },
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
while (1 < argc) {
|
||||
const char *arg = argv[1];
|
||||
if (!strcmp(arg, "--missing-ok"))
|
||||
flags |= WRITE_TREE_MISSING_OK;
|
||||
else if (!prefixcmp(arg, "--prefix="))
|
||||
prefix = arg + 9;
|
||||
else if (!prefixcmp(arg, "--ignore-cache-tree"))
|
||||
/*
|
||||
* This is only useful for debugging, so I
|
||||
* do not bother documenting it.
|
||||
*/
|
||||
flags |= WRITE_TREE_IGNORE_CACHE_TREE;
|
||||
else
|
||||
usage(write_tree_usage);
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (argc > 2)
|
||||
die("too many options");
|
||||
argc = parse_options(argc, argv, unused_prefix, write_tree_options,
|
||||
write_tree_usage, 0);
|
||||
|
||||
ret = write_cache_as_tree(sha1, flags, prefix);
|
||||
switch (ret) {
|
||||
|
||||
3
cache.h
3
cache.h
@@ -468,6 +468,9 @@ extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_obje
|
||||
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
|
||||
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
|
||||
|
||||
/* "careful lstat()" */
|
||||
extern int check_path(const char *path, int len, struct stat *st);
|
||||
|
||||
#define REFRESH_REALLY 0x0001 /* ignore_valid */
|
||||
#define REFRESH_UNMERGED 0x0002 /* allow unmerged */
|
||||
#define REFRESH_QUIET 0x0004 /* be quiet about it */
|
||||
|
||||
1
commit.h
1
commit.h
@@ -64,6 +64,7 @@ enum cmit_fmt {
|
||||
};
|
||||
|
||||
extern int non_ascii(int);
|
||||
extern int has_non_ascii(const char *text);
|
||||
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
|
||||
extern char *reencode_commit_message(const struct commit *commit,
|
||||
const char **encoding_p);
|
||||
|
||||
@@ -17,9 +17,10 @@ typedef int pid_t;
|
||||
#define S_IROTH 0
|
||||
#define S_IXOTH 0
|
||||
|
||||
#define WIFEXITED(x) ((unsigned)(x) < 259) /* STILL_ACTIVE */
|
||||
#define WIFEXITED(x) 1
|
||||
#define WIFSIGNALED(x) 0
|
||||
#define WEXITSTATUS(x) ((x) & 0xff)
|
||||
#define WIFSIGNALED(x) ((unsigned)(x) > 259)
|
||||
#define WTERMSIG(x) SIGTERM
|
||||
|
||||
#define SIGHUP 1
|
||||
#define SIGQUIT 3
|
||||
|
||||
10
config.c
10
config.c
@@ -62,7 +62,8 @@ static char *parse_value(void)
|
||||
if (comment)
|
||||
continue;
|
||||
if (isspace(c) && !quote) {
|
||||
space = 1;
|
||||
if (len)
|
||||
space++;
|
||||
continue;
|
||||
}
|
||||
if (!quote) {
|
||||
@@ -71,11 +72,8 @@ static char *parse_value(void)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (space) {
|
||||
if (len)
|
||||
value[len++] = ' ';
|
||||
space = 0;
|
||||
}
|
||||
for (; space; space--)
|
||||
value[len++] = ' ';
|
||||
if (c == '\\') {
|
||||
c = get_next_char();
|
||||
switch (c) {
|
||||
|
||||
@@ -1047,6 +1047,7 @@ _git_grep ()
|
||||
--extended-regexp --basic-regexp --fixed-strings
|
||||
--files-with-matches --name-only
|
||||
--files-without-match
|
||||
--max-depth
|
||||
--count
|
||||
--and --or --not --all-match
|
||||
"
|
||||
|
||||
@@ -429,16 +429,19 @@ Each entry is a cons of (SHORT-NAME . FULL-NAME)."
|
||||
(git-get-string-sha1
|
||||
(git-call-process-string-display-error "write-tree"))))
|
||||
|
||||
(defun git-commit-tree (buffer tree head)
|
||||
"Call git-commit-tree with buffer as input and return the resulting commit SHA1."
|
||||
(defun git-commit-tree (buffer tree parent)
|
||||
"Create a commit and possibly update HEAD.
|
||||
Create a commit with the message in BUFFER using the tree with hash TREE.
|
||||
Use PARENT as the parent of the new commit. If PARENT is the current \"HEAD\",
|
||||
update the \"HEAD\" reference to the new commit."
|
||||
(let ((author-name (git-get-committer-name))
|
||||
(author-email (git-get-committer-email))
|
||||
(subject "commit (initial): ")
|
||||
author-date log-start log-end args coding-system-for-write)
|
||||
(when head
|
||||
(when parent
|
||||
(setq subject "commit: ")
|
||||
(push "-p" args)
|
||||
(push head args))
|
||||
(push parent args))
|
||||
(with-current-buffer buffer
|
||||
(goto-char (point-min))
|
||||
(if
|
||||
@@ -474,7 +477,7 @@ Each entry is a cons of (SHORT-NAME . FULL-NAME)."
|
||||
(apply #'git-run-command-region
|
||||
buffer log-start log-end env
|
||||
"commit-tree" tree (nreverse args))))))
|
||||
(when commit (git-update-ref "HEAD" commit head subject))
|
||||
(when commit (git-update-ref "HEAD" commit parent subject))
|
||||
commit)))
|
||||
|
||||
(defun git-empty-db-p ()
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"""
|
||||
|
||||
import os, os.path, sys
|
||||
import tempfile, popen2, pickle, getopt
|
||||
import tempfile, pickle, getopt
|
||||
import re
|
||||
|
||||
# Maps hg version -> git version
|
||||
|
||||
@@ -267,7 +267,7 @@ static int filter_buffer(int fd, void *data)
|
||||
|
||||
status = finish_command(&child_process);
|
||||
if (status)
|
||||
error("external filter %s failed %d", params->cmd, -status);
|
||||
error("external filter %s failed %d", params->cmd, status);
|
||||
return (write_err || status);
|
||||
}
|
||||
|
||||
|
||||
12
dir.c
12
dir.c
@@ -861,12 +861,20 @@ int is_empty_dir(const char *path)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int remove_dir_recursively(struct strbuf *path, int only_empty)
|
||||
int remove_dir_recursively(struct strbuf *path, int flag)
|
||||
{
|
||||
DIR *dir = opendir(path->buf);
|
||||
DIR *dir;
|
||||
struct dirent *e;
|
||||
int ret = 0, original_len = path->len, len;
|
||||
int only_empty = (flag & REMOVE_DIR_EMPTY_ONLY);
|
||||
unsigned char submodule_head[20];
|
||||
|
||||
if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
|
||||
!resolve_gitlink_ref(path->buf, "HEAD", submodule_head))
|
||||
/* Do not descend and nuke a nested git work tree. */
|
||||
return 0;
|
||||
|
||||
dir = opendir(path->buf);
|
||||
if (!dir)
|
||||
return -1;
|
||||
if (path->buf[original_len - 1] != '/')
|
||||
|
||||
5
dir.h
5
dir.h
@@ -88,7 +88,10 @@ static inline int is_dot_or_dotdot(const char *name)
|
||||
extern int is_empty_dir(const char *dir);
|
||||
|
||||
extern void setup_standard_excludes(struct dir_struct *dir);
|
||||
extern int remove_dir_recursively(struct strbuf *path, int only_empty);
|
||||
|
||||
#define REMOVE_DIR_EMPTY_ONLY 01
|
||||
#define REMOVE_DIR_KEEP_NESTED_GIT 02
|
||||
extern int remove_dir_recursively(struct strbuf *path, int flag);
|
||||
|
||||
/* tries to remove the path with empty directories along it, ignores ENOENT */
|
||||
extern int remove_path(const char *path);
|
||||
|
||||
15
entry.c
15
entry.c
@@ -175,6 +175,19 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is like 'lstat()', except it refuses to follow symlinks
|
||||
* in the path.
|
||||
*/
|
||||
int check_path(const char *path, int len, struct stat *st)
|
||||
{
|
||||
if (has_symlink_leading_path(path, len)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return lstat(path, st);
|
||||
}
|
||||
|
||||
int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath)
|
||||
{
|
||||
static char path[PATH_MAX + 1];
|
||||
@@ -188,7 +201,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
|
||||
strcpy(path + len, ce->name);
|
||||
len += ce_namelen(ce);
|
||||
|
||||
if (!lstat(path, &st)) {
|
||||
if (!check_path(path, len, &st)) {
|
||||
unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID);
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
20
git-am.sh
20
git-am.sh
@@ -191,6 +191,20 @@ check_patch_format () {
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
if test -z "$patch_format" &&
|
||||
test -n "$l1" &&
|
||||
test -n "$l2" &&
|
||||
test -n "$l3"
|
||||
then
|
||||
# This begins with three non-empty lines. Is this a
|
||||
# piece of e-mail a-la RFC2822? Grab all the headers,
|
||||
# discarding the indented remainder of folded lines,
|
||||
# and see if it looks like that they all begin with the
|
||||
# header field names...
|
||||
sed -n -e '/^$/q' -e '/^[ ]/d' -e p "$1" |
|
||||
egrep -v '^[A-Za-z]+(-[A-Za-z]+)*:' >/dev/null ||
|
||||
patch_format=mbox
|
||||
fi
|
||||
} < "$1" || clean_abort
|
||||
}
|
||||
|
||||
@@ -254,7 +268,11 @@ split_patches () {
|
||||
msgnum=
|
||||
;;
|
||||
*)
|
||||
clean_abort "Patch format $patch_format is not supported."
|
||||
if test -n "$parse_patch" ; then
|
||||
clean_abort "Patch format $patch_format is not supported."
|
||||
else
|
||||
clean_abort "Patch format detection failed."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -252,7 +252,8 @@ sub conn {
|
||||
}
|
||||
};
|
||||
}
|
||||
$pass="A" unless $pass;
|
||||
|
||||
$pass = $self->_scramble($pass);
|
||||
|
||||
my ($s, $rep);
|
||||
if ($proxyhost) {
|
||||
@@ -484,6 +485,42 @@ sub _fetchfile {
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub _scramble {
|
||||
my ($self, $pass) = @_;
|
||||
my $scrambled = "A";
|
||||
|
||||
return $scrambled unless $pass;
|
||||
|
||||
my $pass_len = length($pass);
|
||||
my @pass_arr = split("", $pass);
|
||||
my $i;
|
||||
|
||||
# from cvs/src/scramble.c
|
||||
my @shifts = (
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
|
||||
111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
|
||||
41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
|
||||
125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
|
||||
36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
|
||||
58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
|
||||
225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
|
||||
199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
|
||||
174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
|
||||
207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
|
||||
192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
|
||||
227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
|
||||
182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
|
||||
243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152
|
||||
);
|
||||
|
||||
for ($i = 0; $i < $pass_len; $i++) {
|
||||
$scrambled .= pack("C", $shifts[ord($pass_arr[$i])]);
|
||||
}
|
||||
|
||||
return $scrambled;
|
||||
}
|
||||
|
||||
package main;
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ EOF
|
||||
|
||||
# check to see if Dennis Stosberg's mod_perl compatibility patch
|
||||
# (<20060621130708.Gcbc6e5c@leonov.stosberg.net>) has been applied
|
||||
if test -f "$module_path/mod_perl.so" && grep '^our $gitbin' \
|
||||
if test -f "$module_path/mod_perl.so" && grep 'MOD_PERL' \
|
||||
"$GIT_DIR/gitweb/gitweb.cgi" >/dev/null
|
||||
then
|
||||
# favor mod_perl if available
|
||||
|
||||
32
git-pull.sh
32
git-pull.sh
@@ -119,15 +119,31 @@ error_on_no_merge_candidates () {
|
||||
}
|
||||
|
||||
test true = "$rebase" && {
|
||||
git update-index --ignore-submodules --refresh &&
|
||||
git diff-files --ignore-submodules --quiet &&
|
||||
git diff-index --ignore-submodules --cached --quiet HEAD -- ||
|
||||
die "refusing to pull with rebase: your working tree is not up-to-date"
|
||||
|
||||
if ! git rev-parse -q --verify HEAD >/dev/null
|
||||
then
|
||||
# On an unborn branch
|
||||
if test -f "$GIT_DIR/index"
|
||||
then
|
||||
die "updating an unborn branch with changes added to the index"
|
||||
fi
|
||||
else
|
||||
git update-index --ignore-submodules --refresh &&
|
||||
git diff-files --ignore-submodules --quiet &&
|
||||
git diff-index --ignore-submodules --cached --quiet HEAD -- ||
|
||||
die "refusing to pull with rebase: your working tree is not up-to-date"
|
||||
fi
|
||||
oldremoteref= &&
|
||||
. git-parse-remote &&
|
||||
reflist="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
|
||||
oldremoteref="$(git rev-parse -q --verify \
|
||||
"$reflist")"
|
||||
remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
|
||||
oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
|
||||
for reflog in $(git rev-list -g $remoteref 2>/dev/null)
|
||||
do
|
||||
if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
|
||||
then
|
||||
oldremoteref="$reflog"
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
orig_head=$(git rev-parse -q --verify HEAD)
|
||||
git fetch $verbosity --update-head-ok "$@" || exit 1
|
||||
|
||||
@@ -382,8 +382,10 @@ else
|
||||
fi
|
||||
|
||||
# The tree must be really really clean.
|
||||
if ! git update-index --ignore-submodules --refresh; then
|
||||
die "cannot rebase: you have unstaged changes"
|
||||
if ! git update-index --ignore-submodules --refresh > /dev/null; then
|
||||
echo >&2 "cannot rebase: you have unstaged changes"
|
||||
git diff --name-status -r --ignore-submodules -- >&2
|
||||
exit 1
|
||||
fi
|
||||
diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --)
|
||||
case "$diff" in
|
||||
|
||||
@@ -8,13 +8,33 @@ USAGE='<start> <url> [<end>]'
|
||||
LONG_USAGE='Summarizes the changes between two commits to the standard output,
|
||||
and includes the given URL in the generated summary.'
|
||||
SUBDIRECTORY_OK='Yes'
|
||||
OPTIONS_SPEC=
|
||||
OPTIONS_SPEC='git request-pull [options] start url [end]
|
||||
--
|
||||
p show patch text as well
|
||||
'
|
||||
|
||||
. git-sh-setup
|
||||
. git-parse-remote
|
||||
|
||||
GIT_PAGER=
|
||||
export GIT_PAGER
|
||||
|
||||
patch=
|
||||
while case "$#" in 0) break ;; esac
|
||||
do
|
||||
case "$1" in
|
||||
-p)
|
||||
patch=-p ;;
|
||||
--)
|
||||
shift; break ;;
|
||||
-*)
|
||||
usage ;;
|
||||
*)
|
||||
break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
base=$1
|
||||
url=$2
|
||||
head=${3-HEAD}
|
||||
@@ -54,5 +74,5 @@ echo " $url $branch"
|
||||
echo
|
||||
|
||||
git shortlog ^$baserev $headrev
|
||||
git diff -M --stat --summary $merge_base $headrev
|
||||
git diff -M --stat --summary $patch $merge_base..$headrev
|
||||
exit $status
|
||||
|
||||
@@ -450,7 +450,6 @@ sub check_file_rev_conflict($) {
|
||||
try {
|
||||
$repo->command('rev-parse', '--verify', '--quiet', $f);
|
||||
if (defined($format_patch)) {
|
||||
print "foo\n";
|
||||
return $format_patch;
|
||||
}
|
||||
die(<<EOF);
|
||||
|
||||
99
git-svn.perl
99
git-svn.perl
@@ -764,6 +764,7 @@ sub cmd_show_ignore {
|
||||
print STDOUT "\n# $path\n";
|
||||
my $s = $props->{'svn:ignore'} or return;
|
||||
$s =~ s/[\r\n]+/\n/g;
|
||||
$s =~ s/^\n+//;
|
||||
chomp $s;
|
||||
$s =~ s#^#$path#gm;
|
||||
print STDOUT "$s\n";
|
||||
@@ -801,6 +802,7 @@ sub cmd_create_ignore {
|
||||
open(GITIGNORE, '>', $ignore)
|
||||
or fatal("Failed to open `$ignore' for writing: $!");
|
||||
$s =~ s/[\r\n]+/\n/g;
|
||||
$s =~ s/^\n+//;
|
||||
chomp $s;
|
||||
# Prefix all patterns so that the ignore doesn't apply
|
||||
# to sub-directories.
|
||||
@@ -907,7 +909,7 @@ sub cmd_multi_init {
|
||||
}
|
||||
do_git_init_db();
|
||||
if (defined $_trunk) {
|
||||
my $trunk_ref = $_prefix . 'trunk';
|
||||
my $trunk_ref = 'refs/remotes/' . $_prefix . 'trunk';
|
||||
# try both old-style and new-style lookups:
|
||||
my $gs_trunk = eval { Git::SVN->new($trunk_ref) };
|
||||
unless ($gs_trunk) {
|
||||
@@ -1154,6 +1156,17 @@ sub post_fetch_checkout {
|
||||
my $gs = $Git::SVN::_head or return;
|
||||
return if verify_ref('refs/heads/master^0');
|
||||
|
||||
# look for "trunk" ref if it exists
|
||||
my $remote = Git::SVN::read_all_remotes()->{$gs->{repo_id}};
|
||||
my $fetch = $remote->{fetch};
|
||||
if ($fetch) {
|
||||
foreach my $p (keys %$fetch) {
|
||||
basename($fetch->{$p}) eq 'trunk' or next;
|
||||
$gs = Git::SVN->new($fetch->{$p}, $gs->{repo_id}, $p);
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
my $valid_head = verify_ref('HEAD^0');
|
||||
command_noisy(qw(update-ref refs/heads/master), $gs->refname);
|
||||
return if ($valid_head || !verify_ref('HEAD^0'));
|
||||
@@ -1641,23 +1654,23 @@ sub resolve_local_globs {
|
||||
return unless defined $glob_spec;
|
||||
my $ref = $glob_spec->{ref};
|
||||
my $path = $glob_spec->{path};
|
||||
foreach (command(qw#for-each-ref --format=%(refname) refs/remotes#)) {
|
||||
next unless m#^refs/remotes/$ref->{regex}$#;
|
||||
foreach (command(qw#for-each-ref --format=%(refname) refs/#)) {
|
||||
next unless m#^$ref->{regex}$#;
|
||||
my $p = $1;
|
||||
my $pathname = desanitize_refname($path->full_path($p));
|
||||
my $refname = desanitize_refname($ref->full_path($p));
|
||||
if (my $existing = $fetch->{$pathname}) {
|
||||
if ($existing ne $refname) {
|
||||
die "Refspec conflict:\n",
|
||||
"existing: refs/remotes/$existing\n",
|
||||
" globbed: refs/remotes/$refname\n";
|
||||
"existing: $existing\n",
|
||||
" globbed: $refname\n";
|
||||
}
|
||||
my $u = (::cmt_metadata("refs/remotes/$refname"))[0];
|
||||
my $u = (::cmt_metadata("$refname"))[0];
|
||||
$u =~ s!^\Q$url\E(/|$)!! or die
|
||||
"refs/remotes/$refname: '$url' not found in '$u'\n";
|
||||
"$refname: '$url' not found in '$u'\n";
|
||||
if ($pathname ne $u) {
|
||||
warn "W: Refspec glob conflict ",
|
||||
"(ref: refs/remotes/$refname):\n",
|
||||
"(ref: $refname):\n",
|
||||
"expected path: $pathname\n",
|
||||
" real path: $u\n",
|
||||
"Continuing ahead with $u\n";
|
||||
@@ -1735,33 +1748,35 @@ sub read_all_remotes {
|
||||
my $use_svm_props = eval { command_oneline(qw/config --bool
|
||||
svn.useSvmProps/) };
|
||||
$use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
|
||||
my $svn_refspec = qr{\s*/?(.*?)\s*:\s*(.+?)\s*};
|
||||
foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
|
||||
if (m!^(.+)\.fetch=\s*(.*)\s*:\s*(.+)\s*$!) {
|
||||
my ($remote, $local_ref, $_remote_ref) = ($1, $2, $3);
|
||||
die("svn-remote.$remote: remote ref '$_remote_ref' "
|
||||
. "must start with 'refs/remotes/'\n")
|
||||
unless $_remote_ref =~ m{^refs/remotes/(.+)};
|
||||
my $remote_ref = $1;
|
||||
$local_ref =~ s{^/}{};
|
||||
if (m!^(.+)\.fetch=$svn_refspec$!) {
|
||||
my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
|
||||
die("svn-remote.$remote: remote ref '$remote_ref' "
|
||||
. "must start with 'refs/'\n")
|
||||
unless $remote_ref =~ m{^refs/};
|
||||
$r->{$remote}->{fetch}->{$local_ref} = $remote_ref;
|
||||
$r->{$remote}->{svm} = {} if $use_svm_props;
|
||||
} elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
|
||||
$r->{$1}->{svm} = {};
|
||||
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
|
||||
$r->{$1}->{url} = $2;
|
||||
} elsif (m!^(.+)\.(branches|tags)=
|
||||
(.*):refs/remotes/(.+)\s*$/!x) {
|
||||
my ($p, $g) = ($3, $4);
|
||||
} elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {
|
||||
my ($remote, $t, $local_ref, $remote_ref) =
|
||||
($1, $2, $3, $4);
|
||||
die("svn-remote.$remote: remote ref '$remote_ref' ($t) "
|
||||
. "must start with 'refs/'\n")
|
||||
unless $remote_ref =~ m{^refs/};
|
||||
my $rs = {
|
||||
t => $2,
|
||||
remote => $1,
|
||||
path => Git::SVN::GlobSpec->new($p),
|
||||
ref => Git::SVN::GlobSpec->new($g) };
|
||||
t => $t,
|
||||
remote => $remote,
|
||||
path => Git::SVN::GlobSpec->new($local_ref),
|
||||
ref => Git::SVN::GlobSpec->new($remote_ref) };
|
||||
if (length($rs->{ref}->{right}) != 0) {
|
||||
die "The '*' glob character must be the last ",
|
||||
"character of '$g'\n";
|
||||
"character of '$remote_ref'\n";
|
||||
}
|
||||
push @{ $r->{$1}->{$2} }, $rs;
|
||||
push @{ $r->{$remote}->{$t} }, $rs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1869,9 +1884,9 @@ sub init_remote_config {
|
||||
}
|
||||
}
|
||||
my ($xrepo_id, $xpath) = find_ref($self->refname);
|
||||
if (defined $xpath) {
|
||||
if (!$no_write && defined $xpath) {
|
||||
die "svn-remote.$xrepo_id.fetch already set to track ",
|
||||
"$xpath:refs/remotes/", $self->refname, "\n";
|
||||
"$xpath:", $self->refname, "\n";
|
||||
}
|
||||
unless ($no_write) {
|
||||
command_noisy('config',
|
||||
@@ -1946,7 +1961,7 @@ sub find_ref {
|
||||
my ($ref_id) = @_;
|
||||
foreach (command(qw/config -l/)) {
|
||||
next unless m!^svn-remote\.(.+)\.fetch=
|
||||
\s*(.*)\s*:\s*refs/remotes/(.+)\s*$!x;
|
||||
\s*/?(.*?)\s*:\s*(.+?)\s*$!x;
|
||||
my ($repo_id, $path, $ref) = ($1, $2, $3);
|
||||
if ($ref eq $ref_id) {
|
||||
$path = '' if ($path =~ m#^\./?#);
|
||||
@@ -1963,16 +1978,16 @@ sub new {
|
||||
if (!defined $repo_id) {
|
||||
die "Could not find a \"svn-remote.*.fetch\" key ",
|
||||
"in the repository configuration matching: ",
|
||||
"refs/remotes/$ref_id\n";
|
||||
"$ref_id\n";
|
||||
}
|
||||
}
|
||||
my $self = _new($class, $repo_id, $ref_id, $path);
|
||||
if (!defined $self->{path} || !length $self->{path}) {
|
||||
my $fetch = command_oneline('config', '--get',
|
||||
"svn-remote.$repo_id.fetch",
|
||||
":refs/remotes/$ref_id\$") or
|
||||
":$ref_id\$") or
|
||||
die "Failed to read \"svn-remote.$repo_id.fetch\" ",
|
||||
"\":refs/remotes/$ref_id\$\" in config\n";
|
||||
"\":$ref_id\$\" in config\n";
|
||||
($self->{path}, undef) = split(/\s*:\s*/, $fetch);
|
||||
}
|
||||
$self->{url} = command_oneline('config', '--get',
|
||||
@@ -1983,7 +1998,7 @@ sub new {
|
||||
}
|
||||
|
||||
sub refname {
|
||||
my ($refname) = "refs/remotes/$_[0]->{ref_id}" ;
|
||||
my ($refname) = $_[0]->{ref_id} ;
|
||||
|
||||
# It cannot end with a slash /, we'll throw up on this because
|
||||
# SVN can't have directories with a slash in their name, either:
|
||||
@@ -3262,7 +3277,7 @@ sub _rev_map_get {
|
||||
my $i = int(($l/24 + $u/24) / 2) * 24;
|
||||
sysseek($fh, $i, SEEK_SET) or croak "seek: $!";
|
||||
sysread($fh, my $buf, 24) == 24 or croak "read: $!";
|
||||
my ($r, $c) = unpack('NH40', $buf);
|
||||
my ($r, $c) = unpack(rev_map_fmt, $buf);
|
||||
|
||||
if ($r < $rev) {
|
||||
$l = $i + 24;
|
||||
@@ -3317,12 +3332,24 @@ sub _new {
|
||||
$repo_id = $Git::SVN::default_repo_id;
|
||||
}
|
||||
unless (defined $ref_id && length $ref_id) {
|
||||
$_[2] = $ref_id = $Git::SVN::default_ref_id;
|
||||
$_prefix = '' unless defined($_prefix);
|
||||
$_[2] = $ref_id =
|
||||
"refs/remotes/$_prefix$Git::SVN::default_ref_id";
|
||||
}
|
||||
$_[1] = $repo_id;
|
||||
my $dir = "$ENV{GIT_DIR}/svn/$ref_id";
|
||||
|
||||
# Older repos imported by us used $GIT_DIR/svn/foo instead of
|
||||
# $GIT_DIR/svn/refs/remotes/foo when tracking refs/remotes/foo
|
||||
if ($ref_id =~ m{^refs/remotes/(.*)}) {
|
||||
my $old_dir = "$ENV{GIT_DIR}/svn/$1";
|
||||
if (-d $old_dir && ! -d $dir) {
|
||||
$dir = $old_dir;
|
||||
}
|
||||
}
|
||||
|
||||
$_[3] = $path = '' unless (defined $path);
|
||||
mkpath(["$ENV{GIT_DIR}/svn"]);
|
||||
mkpath([$dir]);
|
||||
bless {
|
||||
ref_id => $ref_id, dir => $dir, index => "$dir/index",
|
||||
path => $path, config => "$ENV{GIT_DIR}/svn/config",
|
||||
@@ -5495,7 +5522,7 @@ sub minimize_connections {
|
||||
my $pfx = "svn-remote.$x->{old_repo_id}";
|
||||
|
||||
my $old_fetch = quotemeta("$x->{old_path}:".
|
||||
"refs/remotes/$x->{ref_id}");
|
||||
"$x->{ref_id}");
|
||||
command_noisy(qw/config --unset/,
|
||||
"$pfx.fetch", '^'. $old_fetch . '$');
|
||||
delete $r->{$x->{old_repo_id}}->
|
||||
@@ -5564,7 +5591,7 @@ sub new {
|
||||
my ($class, $glob) = @_;
|
||||
my $re = $glob;
|
||||
$re =~ s!/+$!!g; # no need for trailing slashes
|
||||
$re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
|
||||
$re =~ m!^([^*]*)(\*(?:/\*)*)(.*)$!;
|
||||
my $temp = $re;
|
||||
my ($left, $right) = ($1, $3);
|
||||
$re = $2;
|
||||
|
||||
10
git.c
10
git.c
@@ -416,13 +416,9 @@ static void execv_dashed_external(const char **argv)
|
||||
* if we fail because the command is not found, it is
|
||||
* OK to return. Otherwise, we just pass along the status code.
|
||||
*/
|
||||
status = run_command_v_opt(argv, 0);
|
||||
if (status != -ERR_RUN_COMMAND_EXEC) {
|
||||
if (IS_RUN_COMMAND_ERR(status))
|
||||
die("unable to run '%s'", argv[0]);
|
||||
exit(-status);
|
||||
}
|
||||
errno = ENOENT; /* as if we called execvp */
|
||||
status = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);
|
||||
if (status >= 0 || errno != ENOENT)
|
||||
exit(status);
|
||||
|
||||
argv[0] = tmp;
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ proc parseviewrevs {view revs} {
|
||||
if {$sdm != 2} {
|
||||
lappend ret $id
|
||||
} else {
|
||||
lset ret end [lindex $ret end]...$id
|
||||
lset ret end $id...[lindex $ret end]
|
||||
}
|
||||
lappend pos $id
|
||||
}
|
||||
@@ -1677,6 +1677,7 @@ proc readrefs {} {
|
||||
global tagids idtags headids idheads tagobjid
|
||||
global otherrefids idotherrefs mainhead mainheadid
|
||||
global selecthead selectheadid
|
||||
global hideremotes
|
||||
|
||||
foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
|
||||
catch {unset $v}
|
||||
@@ -1689,7 +1690,7 @@ proc readrefs {} {
|
||||
if {![string match "refs/*" $ref]} continue
|
||||
set name [string range $ref 5 end]
|
||||
if {[string match "remotes/*" $name]} {
|
||||
if {![string match "*/HEAD" $name]} {
|
||||
if {![string match "*/HEAD" $name] && !$hideremotes} {
|
||||
set headids($name) $id
|
||||
lappend idheads($id) $name
|
||||
}
|
||||
@@ -2520,6 +2521,7 @@ proc savestuff {w} {
|
||||
global cmitmode wrapcomment datetimeformat limitdiffs
|
||||
global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
|
||||
global autoselect extdifftool perfile_attrs markbgcolor
|
||||
global hideremotes
|
||||
|
||||
if {$stuffsaved} return
|
||||
if {![winfo viewable .]} return
|
||||
@@ -2539,6 +2541,7 @@ proc savestuff {w} {
|
||||
puts $f [list set wrapcomment $wrapcomment]
|
||||
puts $f [list set autoselect $autoselect]
|
||||
puts $f [list set showneartags $showneartags]
|
||||
puts $f [list set hideremotes $hideremotes]
|
||||
puts $f [list set showlocalchanges $showlocalchanges]
|
||||
puts $f [list set datetimeformat $datetimeformat]
|
||||
puts $f [list set limitdiffs $limitdiffs]
|
||||
@@ -7907,6 +7910,11 @@ proc gotocommit {} {
|
||||
}
|
||||
set id [lindex $matches 0]
|
||||
}
|
||||
} else {
|
||||
if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
|
||||
error_popup [mc "Revision %s is not known" $sha1string]
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if {[commitinview $id $curview]} {
|
||||
@@ -7916,7 +7924,7 @@ proc gotocommit {} {
|
||||
if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
|
||||
set msg [mc "SHA1 id %s is not known" $sha1string]
|
||||
} else {
|
||||
set msg [mc "Tag/Head %s is not known" $sha1string]
|
||||
set msg [mc "Revision %s is not in the current view" $sha1string]
|
||||
}
|
||||
error_popup $msg
|
||||
}
|
||||
@@ -10384,6 +10392,7 @@ proc doprefs {} {
|
||||
global oldprefs prefstop showneartags showlocalchanges
|
||||
global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
|
||||
global tabstop limitdiffs autoselect extdifftool perfile_attrs
|
||||
global hideremotes
|
||||
|
||||
set top .gitkprefs
|
||||
set prefstop $top
|
||||
@@ -10392,7 +10401,7 @@ proc doprefs {} {
|
||||
return
|
||||
}
|
||||
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
|
||||
limitdiffs tabstop perfile_attrs} {
|
||||
limitdiffs tabstop perfile_attrs hideremotes} {
|
||||
set oldprefs($v) [set $v]
|
||||
}
|
||||
toplevel $top
|
||||
@@ -10424,6 +10433,9 @@ proc doprefs {} {
|
||||
checkbutton $top.ntag -text [mc "Display nearby tags"] \
|
||||
-font optionfont -variable showneartags
|
||||
grid x $top.ntag -sticky w
|
||||
checkbutton $top.hideremotes -text [mc "Hide remote refs"] \
|
||||
-font optionfont -variable hideremotes
|
||||
grid x $top.hideremotes -sticky w
|
||||
checkbutton $top.ldiff -text [mc "Limit diffs to listed paths"] \
|
||||
-font optionfont -variable limitdiffs
|
||||
grid x $top.ldiff -sticky w
|
||||
@@ -10548,7 +10560,7 @@ proc prefscan {} {
|
||||
global oldprefs prefstop
|
||||
|
||||
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
|
||||
limitdiffs tabstop perfile_attrs} {
|
||||
limitdiffs tabstop perfile_attrs hideremotes} {
|
||||
global $v
|
||||
set $v $oldprefs($v)
|
||||
}
|
||||
@@ -10562,6 +10574,7 @@ proc prefsok {} {
|
||||
global oldprefs prefstop showneartags showlocalchanges
|
||||
global fontpref mainfont textfont uifont
|
||||
global limitdiffs treediffs perfile_attrs
|
||||
global hideremotes
|
||||
|
||||
catch {destroy $prefstop}
|
||||
unset prefstop
|
||||
@@ -10607,6 +10620,9 @@ proc prefsok {} {
|
||||
$limitdiffs != $oldprefs(limitdiffs)} {
|
||||
reselectline
|
||||
}
|
||||
if {$hideremotes != $oldprefs(hideremotes)} {
|
||||
rereadrefs
|
||||
}
|
||||
}
|
||||
|
||||
proc formatdate {d} {
|
||||
@@ -10902,7 +10918,7 @@ proc gitattr {path attr default} {
|
||||
} else {
|
||||
set r "unspecified"
|
||||
if {![catch {set line [exec git check-attr $attr -- $path]}]} {
|
||||
regexp "(.*): encoding: (.*)" $line m f r
|
||||
regexp "(.*): $attr: (.*)" $line m f r
|
||||
}
|
||||
set path_attr_cache($attr,$path) $r
|
||||
}
|
||||
@@ -10930,7 +10946,7 @@ proc cache_gitattr {attr pathlist} {
|
||||
set newlist [lrange $newlist $lim end]
|
||||
if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
|
||||
foreach row [split $rlist "\n"] {
|
||||
if {[regexp "(.*): encoding: (.*)" $row m path value]} {
|
||||
if {[regexp "(.*): $attr: (.*)" $row m path value]} {
|
||||
if {[string index $path 0] eq "\""} {
|
||||
set path [encoding convertfrom [lindex $path 0]]
|
||||
}
|
||||
@@ -11012,6 +11028,7 @@ set mingaplen 100
|
||||
set cmitmode "patch"
|
||||
set wrapcomment "none"
|
||||
set showneartags 1
|
||||
set hideremotes 0
|
||||
set maxrefs 20
|
||||
set maxlinelen 200
|
||||
set showlocalchanges 1
|
||||
|
||||
@@ -165,6 +165,12 @@ not include variables usually directly set during build):
|
||||
Full URL and absolute URL of gitweb script;
|
||||
in earlier versions of gitweb you might have need to set those
|
||||
variables, now there should be no need to do it.
|
||||
* $base_url
|
||||
Base URL for relative URLs in pages generated by gitweb,
|
||||
(e.g. $logo, $favicon, @stylesheets if they are relative URLs),
|
||||
needed and used only for URLs with nonempty PATH_INFO via
|
||||
<base href="$base_url>. Usually gitweb sets its value correctly,
|
||||
and there is no need to set this variable, e.g. to $my_uri or "/".
|
||||
* $home_link
|
||||
Target of the home link on top of all pages (the first part of view
|
||||
"breadcrumbs"). By default set to absolute URI of a page ($my_uri).
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 164 B After Width: | Height: | Size: 115 B |
Binary file not shown.
|
Before Width: | Height: | Size: 208 B After Width: | Height: | Size: 207 B |
@@ -226,22 +226,30 @@ th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
tr.light:hover {
|
||||
background-color: #edece6;
|
||||
/* do not change row style on hover for 'blame' view */
|
||||
tr.light,
|
||||
table.blame .light:hover {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
tr.dark {
|
||||
background-color: #f6f6f0;
|
||||
}
|
||||
|
||||
tr.dark2 {
|
||||
tr.dark,
|
||||
table.blame .dark:hover {
|
||||
background-color: #f6f6f0;
|
||||
}
|
||||
|
||||
/* currently both use the same, but it can change */
|
||||
tr.light:hover,
|
||||
tr.dark:hover {
|
||||
background-color: #edece6;
|
||||
}
|
||||
|
||||
/* boundary commits in 'blame' view */
|
||||
/* and commits without "previous" */
|
||||
tr.boundary td.sha1,
|
||||
tr.no-previous td.linenr {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 2px 5px;
|
||||
font-size: 100%;
|
||||
@@ -262,7 +270,7 @@ td.sha1 {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
td.error {
|
||||
.error {
|
||||
color: red;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
@@ -940,10 +940,13 @@ sub href {
|
||||
if (defined $params{'hash_parent_base'}) {
|
||||
$href .= esc_url($params{'hash_parent_base'});
|
||||
# skip the file_parent if it's the same as the file_name
|
||||
delete $params{'file_parent'} if $params{'file_parent'} eq $params{'file_name'};
|
||||
if (defined $params{'file_parent'} && $params{'file_parent'} !~ /\.\./) {
|
||||
$href .= ":/".esc_url($params{'file_parent'});
|
||||
delete $params{'file_parent'};
|
||||
if (defined $params{'file_parent'}) {
|
||||
if (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) {
|
||||
delete $params{'file_parent'};
|
||||
} elsif ($params{'file_parent'} !~ /\.\./) {
|
||||
$href .= ":/".esc_url($params{'file_parent'});
|
||||
delete $params{'file_parent'};
|
||||
}
|
||||
}
|
||||
$href .= "..";
|
||||
delete $params{'hash_parent'};
|
||||
@@ -2570,7 +2573,7 @@ sub parse_commit_text {
|
||||
} elsif ((!defined $withparents) && ($line =~ m/^parent ([0-9a-fA-F]{40})$/)) {
|
||||
push @parents, $1;
|
||||
} elsif ($line =~ m/^author (.*) ([0-9]+) (.*)$/) {
|
||||
$co{'author'} = $1;
|
||||
$co{'author'} = to_utf8($1);
|
||||
$co{'author_epoch'} = $2;
|
||||
$co{'author_tz'} = $3;
|
||||
if ($co{'author'} =~ m/^([^<]+) <([^>]*)>/) {
|
||||
@@ -2580,10 +2583,9 @@ sub parse_commit_text {
|
||||
$co{'author_name'} = $co{'author'};
|
||||
}
|
||||
} elsif ($line =~ m/^committer (.*) ([0-9]+) (.*)$/) {
|
||||
$co{'committer'} = $1;
|
||||
$co{'committer'} = to_utf8($1);
|
||||
$co{'committer_epoch'} = $2;
|
||||
$co{'committer_tz'} = $3;
|
||||
$co{'committer_name'} = $co{'committer'};
|
||||
if ($co{'committer'} =~ m/^([^<]+) <([^>]*)>/) {
|
||||
$co{'committer_name'} = $1;
|
||||
$co{'committer_email'} = $2;
|
||||
@@ -4801,7 +4803,7 @@ sub git_blame {
|
||||
git_print_page_path($file_name, $ftype, $hash_base);
|
||||
|
||||
# page body
|
||||
my @rev_color = qw(light2 dark2);
|
||||
my @rev_color = qw(light dark);
|
||||
my $num_colors = scalar(@rev_color);
|
||||
my $current_color = 0;
|
||||
my %metainfo = ();
|
||||
@@ -4819,15 +4821,18 @@ HTML
|
||||
my ($full_rev, $orig_lineno, $lineno, $group_size) =
|
||||
($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/);
|
||||
if (!exists $metainfo{$full_rev}) {
|
||||
$metainfo{$full_rev} = {};
|
||||
$metainfo{$full_rev} = { 'nprevious' => 0 };
|
||||
}
|
||||
my $meta = $metainfo{$full_rev};
|
||||
my $data;
|
||||
while ($data = <$fd>) {
|
||||
chomp $data;
|
||||
last if ($data =~ s/^\t//); # contents of line
|
||||
if ($data =~ /^(\S+) (.*)$/) {
|
||||
$meta->{$1} = $2;
|
||||
if ($data =~ /^(\S+)(?: (.*))?$/) {
|
||||
$meta->{$1} = $2 unless exists $meta->{$1};
|
||||
}
|
||||
if ($data =~ /^previous /) {
|
||||
$meta->{'nprevious'}++;
|
||||
}
|
||||
}
|
||||
my $short_rev = substr($full_rev, 0, 8);
|
||||
@@ -4838,7 +4843,11 @@ HTML
|
||||
if ($group_size) {
|
||||
$current_color = ($current_color + 1) % $num_colors;
|
||||
}
|
||||
print "<tr id=\"l$lineno\" class=\"$rev_color[$current_color]\">\n";
|
||||
my $tr_class = $rev_color[$current_color];
|
||||
$tr_class .= ' boundary' if (exists $meta->{'boundary'});
|
||||
$tr_class .= ' no-previous' if ($meta->{'nprevious'} == 0);
|
||||
$tr_class .= ' multiple-previous' if ($meta->{'nprevious'} > 1);
|
||||
print "<tr id=\"l$lineno\" class=\"$tr_class\">\n";
|
||||
if ($group_size) {
|
||||
print "<td class=\"sha1\"";
|
||||
print " title=\"". esc_html($author) . ", $date\"";
|
||||
@@ -4848,22 +4857,31 @@ HTML
|
||||
hash=>$full_rev,
|
||||
file_name=>$file_name)},
|
||||
esc_html($short_rev));
|
||||
if ($group_size >= 2) {
|
||||
my @author_initials = ($author =~ /\b([[:upper:]])\B/g);
|
||||
if (@author_initials) {
|
||||
print "<br />" .
|
||||
esc_html(join('', @author_initials));
|
||||
# or join('.', ...)
|
||||
}
|
||||
}
|
||||
print "</td>\n";
|
||||
}
|
||||
my $parent_commit;
|
||||
if (!exists $meta->{'parent'}) {
|
||||
open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
|
||||
or die_error(500, "Open git-rev-parse failed");
|
||||
$parent_commit = <$dd>;
|
||||
close $dd;
|
||||
chomp($parent_commit);
|
||||
$meta->{'parent'} = $parent_commit;
|
||||
} else {
|
||||
$parent_commit = $meta->{'parent'};
|
||||
# 'previous' <sha1 of parent commit> <filename at commit>
|
||||
if (exists $meta->{'previous'} &&
|
||||
$meta->{'previous'} =~ /^([a-fA-F0-9]{40}) (.*)$/) {
|
||||
$meta->{'parent'} = $1;
|
||||
$meta->{'file_parent'} = unquote($2);
|
||||
}
|
||||
my $linenr_commit =
|
||||
exists($meta->{'parent'}) ?
|
||||
$meta->{'parent'} : $full_rev;
|
||||
my $linenr_filename =
|
||||
exists($meta->{'file_parent'}) ?
|
||||
$meta->{'file_parent'} : unquote($meta->{'filename'});
|
||||
my $blamed = href(action => 'blame',
|
||||
file_name => $meta->{'filename'},
|
||||
hash_base => $parent_commit);
|
||||
file_name => $linenr_filename,
|
||||
hash_base => $linenr_commit);
|
||||
print "<td class=\"linenr\">";
|
||||
print $cgi->a({ -href => "$blamed#l$orig_lineno",
|
||||
-class => "linenr" },
|
||||
|
||||
1
grep.h
1
grep.h
@@ -79,6 +79,7 @@ struct grep_opt {
|
||||
int pathname;
|
||||
int null_following_name;
|
||||
int color;
|
||||
int max_depth;
|
||||
int funcname;
|
||||
char color_match[COLOR_MAXLEN];
|
||||
const char *color_external;
|
||||
|
||||
4
help.c
4
help.c
@@ -302,7 +302,7 @@ const char *help_unknown_cmd(const char *cmd)
|
||||
struct cmdnames main_cmds, other_cmds;
|
||||
|
||||
memset(&main_cmds, 0, sizeof(main_cmds));
|
||||
memset(&other_cmds, 0, sizeof(main_cmds));
|
||||
memset(&other_cmds, 0, sizeof(other_cmds));
|
||||
memset(&aliases, 0, sizeof(aliases));
|
||||
|
||||
git_config(git_unknown_cmd_config, NULL);
|
||||
@@ -334,7 +334,7 @@ const char *help_unknown_cmd(const char *cmd)
|
||||
const char *assumed = main_cmds.names[0]->name;
|
||||
main_cmds.names[0] = NULL;
|
||||
clean_cmdnames(&main_cmds);
|
||||
fprintf(stderr, "WARNING: You called a Git program named '%s', "
|
||||
fprintf(stderr, "WARNING: You called a Git command named '%s', "
|
||||
"which does not exist.\n"
|
||||
"Continuing under the assumption that you meant '%s'\n",
|
||||
cmd, assumed);
|
||||
|
||||
22
http.c
22
http.c
@@ -1004,7 +1004,6 @@ int finish_http_pack_request(struct http_pack_request *preq)
|
||||
struct http_pack_request *new_http_pack_request(
|
||||
struct packed_git *target, const char *base_url)
|
||||
{
|
||||
char *url;
|
||||
char *filename;
|
||||
long prev_posn = 0;
|
||||
char range[RANGE_HEADER_SIZE];
|
||||
@@ -1018,8 +1017,7 @@ struct http_pack_request *new_http_pack_request(
|
||||
end_url_with_slash(&buf, base_url);
|
||||
strbuf_addf(&buf, "objects/pack/pack-%s.pack",
|
||||
sha1_to_hex(target->sha1));
|
||||
url = strbuf_detach(&buf, NULL);
|
||||
preq->url = xstrdup(url);
|
||||
preq->url = strbuf_detach(&buf, NULL);
|
||||
|
||||
filename = sha1_pack_name(target->sha1);
|
||||
snprintf(preq->filename, sizeof(preq->filename), "%s", filename);
|
||||
@@ -1035,7 +1033,7 @@ struct http_pack_request *new_http_pack_request(
|
||||
preq->slot->local = preq->packfile;
|
||||
curl_easy_setopt(preq->slot->curl, CURLOPT_FILE, preq->packfile);
|
||||
curl_easy_setopt(preq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
|
||||
curl_easy_setopt(preq->slot->curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(preq->slot->curl, CURLOPT_URL, preq->url);
|
||||
curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
|
||||
no_pragma_header);
|
||||
|
||||
@@ -1059,6 +1057,8 @@ struct http_pack_request *new_http_pack_request(
|
||||
|
||||
abort:
|
||||
free(filename);
|
||||
free(preq->url);
|
||||
free(preq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1098,7 +1098,6 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
||||
char *hex = sha1_to_hex(sha1);
|
||||
char *filename;
|
||||
char prevfile[PATH_MAX];
|
||||
char *url;
|
||||
int prevlocal;
|
||||
unsigned char prev_buf[PREV_BUF_SIZE];
|
||||
ssize_t prev_read = 0;
|
||||
@@ -1152,8 +1151,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
||||
|
||||
git_SHA1_Init(&freq->c);
|
||||
|
||||
url = get_remote_object_url(base_url, hex, 0);
|
||||
freq->url = xstrdup(url);
|
||||
freq->url = get_remote_object_url(base_url, hex, 0);
|
||||
|
||||
/*
|
||||
* If a previous temp file is present, process what was already
|
||||
@@ -1189,7 +1187,11 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
||||
if (prev_posn>0) {
|
||||
prev_posn = 0;
|
||||
lseek(freq->localfile, 0, SEEK_SET);
|
||||
ftruncate(freq->localfile, 0);
|
||||
if (ftruncate(freq->localfile, 0) < 0) {
|
||||
error("Couldn't truncate temporary file %s for %s: %s",
|
||||
freq->tmpfile, freq->filename, strerror(errno));
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1198,7 +1200,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
||||
curl_easy_setopt(freq->slot->curl, CURLOPT_FILE, freq);
|
||||
curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
|
||||
curl_easy_setopt(freq->slot->curl, CURLOPT_ERRORBUFFER, freq->errorstr);
|
||||
curl_easy_setopt(freq->slot->curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(freq->slot->curl, CURLOPT_URL, freq->url);
|
||||
curl_easy_setopt(freq->slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
|
||||
|
||||
/*
|
||||
@@ -1218,9 +1220,9 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
||||
|
||||
return freq;
|
||||
|
||||
free(url);
|
||||
abort:
|
||||
free(filename);
|
||||
free(freq->url);
|
||||
free(freq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -192,10 +192,6 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
|
||||
|
||||
args[2] = cmd.buf;
|
||||
status = run_command_v_opt(args, 0);
|
||||
if (status < -ERR_RUN_COMMAND_FORK)
|
||||
; /* failure in run-command */
|
||||
else
|
||||
status = -status;
|
||||
fd = open(temp[1], O_RDONLY);
|
||||
if (fd < 0)
|
||||
goto bad;
|
||||
|
||||
12
log-tree.c
12
log-tree.c
@@ -168,18 +168,6 @@ static unsigned int digits_in_number(unsigned int number)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int has_non_ascii(const char *s)
|
||||
{
|
||||
int ch;
|
||||
if (!s)
|
||||
return 0;
|
||||
while ((ch = *s++) != '\0') {
|
||||
if (non_ascii(ch))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_patch_filename(struct commit *commit, int nr, const char *suffix,
|
||||
struct strbuf *buf)
|
||||
{
|
||||
|
||||
@@ -952,9 +952,31 @@ static int process_renames(struct merge_options *o,
|
||||
"%s added in %s",
|
||||
ren1_src, ren1_dst, branch1,
|
||||
ren1_dst, branch2);
|
||||
new_path = unique_path(o, ren1_dst, branch2);
|
||||
output(o, 1, "Adding as %s instead", new_path);
|
||||
update_file(o, 0, dst_other.sha1, dst_other.mode, new_path);
|
||||
if (o->call_depth) {
|
||||
struct merge_file_info mfi;
|
||||
struct diff_filespec one, a, b;
|
||||
|
||||
one.path = a.path = b.path =
|
||||
(char *)ren1_dst;
|
||||
hashcpy(one.sha1, null_sha1);
|
||||
one.mode = 0;
|
||||
hashcpy(a.sha1, ren1->pair->two->sha1);
|
||||
a.mode = ren1->pair->two->mode;
|
||||
hashcpy(b.sha1, dst_other.sha1);
|
||||
b.mode = dst_other.mode;
|
||||
mfi = merge_file(o, &one, &a, &b,
|
||||
branch1,
|
||||
branch2);
|
||||
output(o, 1, "Adding merged %s", ren1_dst);
|
||||
update_file(o, 0,
|
||||
mfi.sha,
|
||||
mfi.mode,
|
||||
ren1_dst);
|
||||
} else {
|
||||
new_path = unique_path(o, ren1_dst, branch2);
|
||||
output(o, 1, "Adding as %s instead", new_path);
|
||||
update_file(o, 0, dst_other.sha1, dst_other.mode, new_path);
|
||||
}
|
||||
} else if ((item = string_list_lookup(ren1_dst, renames2Dst))) {
|
||||
ren2 = item->util;
|
||||
clean_merge = 0;
|
||||
|
||||
@@ -511,7 +511,7 @@ static int usage_with_options_internal(const char * const *usagestr,
|
||||
continue;
|
||||
|
||||
pos = fprintf(stderr, " ");
|
||||
if (opts->short_name) {
|
||||
if (opts->short_name && !(opts->flags & PARSE_OPT_NEGHELP)) {
|
||||
if (opts->flags & PARSE_OPT_NODASH)
|
||||
pos += fprintf(stderr, "%c", opts->short_name);
|
||||
else
|
||||
@@ -520,7 +520,9 @@ static int usage_with_options_internal(const char * const *usagestr,
|
||||
if (opts->long_name && opts->short_name)
|
||||
pos += fprintf(stderr, ", ");
|
||||
if (opts->long_name)
|
||||
pos += fprintf(stderr, "--%s", opts->long_name);
|
||||
pos += fprintf(stderr, "--%s%s",
|
||||
(opts->flags & PARSE_OPT_NEGHELP) ? "no-" : "",
|
||||
opts->long_name);
|
||||
if (opts->type == OPTION_NUMBER)
|
||||
pos += fprintf(stderr, "-NUM");
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ enum parse_opt_option_flags {
|
||||
PARSE_OPT_LASTARG_DEFAULT = 16,
|
||||
PARSE_OPT_NODASH = 32,
|
||||
PARSE_OPT_LITERAL_ARGHELP = 64,
|
||||
PARSE_OPT_NEGHELP = 128,
|
||||
};
|
||||
|
||||
struct option;
|
||||
@@ -80,6 +81,9 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
|
||||
* PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
|
||||
* (i.e. '<argh>') in the help message.
|
||||
* Useful for options with multiple parameters.
|
||||
* PARSE_OPT_NEGHELP: says that the long option should always be shown with
|
||||
* the --no prefix in the usage message. Sometimes
|
||||
* useful for users of OPTION_NEGBIT.
|
||||
*
|
||||
* `callback`::
|
||||
* pointer to the callback to use for OPTION_CALLBACK.
|
||||
|
||||
12
pretty.c
12
pretty.c
@@ -86,6 +86,18 @@ int non_ascii(int ch)
|
||||
return !isascii(ch) || ch == '\033';
|
||||
}
|
||||
|
||||
int has_non_ascii(const char *s)
|
||||
{
|
||||
int ch;
|
||||
if (!s)
|
||||
return 0;
|
||||
while ((ch = *s++) != '\0') {
|
||||
if (non_ascii(ch))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_rfc2047_special(char ch)
|
||||
{
|
||||
return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_'));
|
||||
|
||||
2
refs.c
2
refs.c
@@ -821,7 +821,7 @@ static int remove_empty_directories(const char *file)
|
||||
strbuf_init(&path, 20);
|
||||
strbuf_addstr(&path, file);
|
||||
|
||||
result = remove_dir_recursively(&path, 1);
|
||||
result = remove_dir_recursively(&path, REMOVE_DIR_EMPTY_ONLY);
|
||||
|
||||
strbuf_release(&path);
|
||||
|
||||
|
||||
101
run-command.c
101
run-command.c
@@ -19,6 +19,7 @@ int start_command(struct child_process *cmd)
|
||||
{
|
||||
int need_in, need_out, need_err;
|
||||
int fdin[2], fdout[2], fderr[2];
|
||||
int failed_errno = failed_errno;
|
||||
|
||||
/*
|
||||
* In case of errors we must keep the promise to close FDs
|
||||
@@ -28,9 +29,10 @@ int start_command(struct child_process *cmd)
|
||||
need_in = !cmd->no_stdin && cmd->in < 0;
|
||||
if (need_in) {
|
||||
if (pipe(fdin) < 0) {
|
||||
failed_errno = errno;
|
||||
if (cmd->out > 0)
|
||||
close(cmd->out);
|
||||
return -ERR_RUN_COMMAND_PIPE;
|
||||
goto fail_pipe;
|
||||
}
|
||||
cmd->in = fdin[1];
|
||||
}
|
||||
@@ -40,11 +42,12 @@ int start_command(struct child_process *cmd)
|
||||
&& cmd->out < 0;
|
||||
if (need_out) {
|
||||
if (pipe(fdout) < 0) {
|
||||
failed_errno = errno;
|
||||
if (need_in)
|
||||
close_pair(fdin);
|
||||
else if (cmd->in)
|
||||
close(cmd->in);
|
||||
return -ERR_RUN_COMMAND_PIPE;
|
||||
goto fail_pipe;
|
||||
}
|
||||
cmd->out = fdout[0];
|
||||
}
|
||||
@@ -52,6 +55,7 @@ int start_command(struct child_process *cmd)
|
||||
need_err = !cmd->no_stderr && cmd->err < 0;
|
||||
if (need_err) {
|
||||
if (pipe(fderr) < 0) {
|
||||
failed_errno = errno;
|
||||
if (need_in)
|
||||
close_pair(fdin);
|
||||
else if (cmd->in)
|
||||
@@ -60,7 +64,11 @@ int start_command(struct child_process *cmd)
|
||||
close_pair(fdout);
|
||||
else if (cmd->out)
|
||||
close(cmd->out);
|
||||
return -ERR_RUN_COMMAND_PIPE;
|
||||
fail_pipe:
|
||||
error("cannot create pipe for %s: %s",
|
||||
cmd->argv[0], strerror(failed_errno));
|
||||
errno = failed_errno;
|
||||
return -1;
|
||||
}
|
||||
cmd->err = fderr[0];
|
||||
}
|
||||
@@ -122,6 +130,9 @@ int start_command(struct child_process *cmd)
|
||||
strerror(errno));
|
||||
exit(127);
|
||||
}
|
||||
if (cmd->pid < 0)
|
||||
error("cannot fork() for %s: %s", cmd->argv[0],
|
||||
strerror(failed_errno = errno));
|
||||
#else
|
||||
int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
|
||||
const char **sargv = cmd->argv;
|
||||
@@ -173,6 +184,9 @@ int start_command(struct child_process *cmd)
|
||||
}
|
||||
|
||||
cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
|
||||
failed_errno = errno;
|
||||
if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
|
||||
error("cannot spawn %s: %s", cmd->argv[0], strerror(errno));
|
||||
|
||||
if (cmd->env)
|
||||
free_environ(env);
|
||||
@@ -189,7 +203,6 @@ int start_command(struct child_process *cmd)
|
||||
#endif
|
||||
|
||||
if (cmd->pid < 0) {
|
||||
int err = errno;
|
||||
if (need_in)
|
||||
close_pair(fdin);
|
||||
else if (cmd->in)
|
||||
@@ -200,9 +213,8 @@ int start_command(struct child_process *cmd)
|
||||
close(cmd->out);
|
||||
if (need_err)
|
||||
close_pair(fderr);
|
||||
return err == ENOENT ?
|
||||
-ERR_RUN_COMMAND_EXEC :
|
||||
-ERR_RUN_COMMAND_FORK;
|
||||
errno = failed_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (need_in)
|
||||
@@ -221,40 +233,51 @@ int start_command(struct child_process *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_or_whine(pid_t pid)
|
||||
static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
|
||||
{
|
||||
for (;;) {
|
||||
int status, code;
|
||||
pid_t waiting = waitpid(pid, &status, 0);
|
||||
int status, code = -1;
|
||||
pid_t waiting;
|
||||
int failed_errno = 0;
|
||||
|
||||
if (waiting < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
error("waitpid failed (%s)", strerror(errno));
|
||||
return -ERR_RUN_COMMAND_WAITPID;
|
||||
}
|
||||
if (waiting != pid)
|
||||
return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
|
||||
if (WIFSIGNALED(status))
|
||||
return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
|
||||
while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
|
||||
; /* nothing */
|
||||
|
||||
if (!WIFEXITED(status))
|
||||
return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
|
||||
if (waiting < 0) {
|
||||
failed_errno = errno;
|
||||
error("waitpid for %s failed: %s", argv0, strerror(errno));
|
||||
} else if (waiting != pid) {
|
||||
error("waitpid is confused (%s)", argv0);
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
code = WTERMSIG(status);
|
||||
error("%s died of signal %d", argv0, code);
|
||||
/*
|
||||
* This return value is chosen so that code & 0xff
|
||||
* mimics the exit code that a POSIX shell would report for
|
||||
* a program that died from this signal.
|
||||
*/
|
||||
code -= 128;
|
||||
} else if (WIFEXITED(status)) {
|
||||
code = WEXITSTATUS(status);
|
||||
switch (code) {
|
||||
case 127:
|
||||
return -ERR_RUN_COMMAND_EXEC;
|
||||
case 0:
|
||||
return 0;
|
||||
default:
|
||||
return -code;
|
||||
/*
|
||||
* Convert special exit code when execvp failed.
|
||||
*/
|
||||
if (code == 127) {
|
||||
code = -1;
|
||||
failed_errno = ENOENT;
|
||||
if (!silent_exec_failure)
|
||||
error("cannot run %s: %s", argv0,
|
||||
strerror(ENOENT));
|
||||
}
|
||||
} else {
|
||||
error("waitpid is confused (%s)", argv0);
|
||||
}
|
||||
errno = failed_errno;
|
||||
return code;
|
||||
}
|
||||
|
||||
int finish_command(struct child_process *cmd)
|
||||
{
|
||||
return wait_or_whine(cmd->pid);
|
||||
return wait_or_whine(cmd->pid, cmd->argv[0], cmd->silent_exec_failure);
|
||||
}
|
||||
|
||||
int run_command(struct child_process *cmd)
|
||||
@@ -274,6 +297,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,
|
||||
cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
|
||||
cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
|
||||
cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
|
||||
cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
|
||||
}
|
||||
|
||||
int run_command_v_opt(const char **argv, int opt)
|
||||
@@ -338,10 +362,7 @@ int start_async(struct async *async)
|
||||
int finish_async(struct async *async)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
int ret = 0;
|
||||
|
||||
if (wait_or_whine(async->pid))
|
||||
ret = error("waitpid (async) failed");
|
||||
int ret = wait_or_whine(async->pid, "child process", 0);
|
||||
#else
|
||||
DWORD ret = 0;
|
||||
if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
|
||||
@@ -385,15 +406,7 @@ int run_hook(const char *index_file, const char *name, ...)
|
||||
hook.env = env;
|
||||
}
|
||||
|
||||
ret = start_command(&hook);
|
||||
ret = run_command(&hook);
|
||||
free(argv);
|
||||
if (ret) {
|
||||
warning("Could not spawn %s", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
ret = finish_command(&hook);
|
||||
if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL)
|
||||
warning("%s exited due to uncaught signal", argv[0]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
#ifndef RUN_COMMAND_H
|
||||
#define RUN_COMMAND_H
|
||||
|
||||
enum {
|
||||
ERR_RUN_COMMAND_FORK = 10000,
|
||||
ERR_RUN_COMMAND_EXEC,
|
||||
ERR_RUN_COMMAND_PIPE,
|
||||
ERR_RUN_COMMAND_WAITPID,
|
||||
ERR_RUN_COMMAND_WAITPID_WRONG_PID,
|
||||
ERR_RUN_COMMAND_WAITPID_SIGNAL,
|
||||
ERR_RUN_COMMAND_WAITPID_NOEXIT,
|
||||
};
|
||||
#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)
|
||||
|
||||
struct child_process {
|
||||
const char **argv;
|
||||
pid_t pid;
|
||||
@@ -42,6 +31,7 @@ struct child_process {
|
||||
unsigned no_stdout:1;
|
||||
unsigned no_stderr:1;
|
||||
unsigned git_cmd:1; /* if this is to be git sub-command */
|
||||
unsigned silent_exec_failure:1;
|
||||
unsigned stdout_to_stderr:1;
|
||||
void (*preexec_cb)(void);
|
||||
};
|
||||
@@ -55,6 +45,7 @@ extern int run_hook(const char *index_file, const char *name, ...);
|
||||
#define RUN_COMMAND_NO_STDIN 1
|
||||
#define RUN_GIT_CMD 2 /*If this is to be git sub-command */
|
||||
#define RUN_COMMAND_STDOUT_TO_STDERR 4
|
||||
#define RUN_SILENT_EXEC_FAILURE 8
|
||||
int run_command_v_opt(const char **argv, int opt);
|
||||
|
||||
/*
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
struct send_pack_args {
|
||||
unsigned verbose:1,
|
||||
quiet:1,
|
||||
send_mirror:1,
|
||||
force_update:1,
|
||||
use_thin_pack:1,
|
||||
|
||||
@@ -91,6 +91,10 @@ static int lstat_cache(struct cache_def *cache, const char *name, int len,
|
||||
longest_path_match(name, len, cache->path, cache->len,
|
||||
&previous_slash);
|
||||
match_flags = cache->flags & track_flags & (FL_NOENT|FL_SYMLINK);
|
||||
|
||||
if (!(track_flags & FL_FULLPATH) && match_len == len)
|
||||
match_len = last_slash = previous_slash;
|
||||
|
||||
if (match_flags && match_len == cache->len)
|
||||
return match_flags;
|
||||
/*
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# Copyright (c) 2005 Junio C Hamano
|
||||
#
|
||||
|
||||
-include ../config.mak
|
||||
|
||||
#GIT_TEST_OPTS=--verbose --debug
|
||||
SHELL_PATH ?= $(SHELL)
|
||||
TAR ?= $(TAR)
|
||||
|
||||
75
t/lib-cvs.sh
Normal file
75
t/lib-cvs.sh
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/bin/sh
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
unset CVS_SERVER
|
||||
# for clean cvsps cache
|
||||
HOME=$(pwd)
|
||||
export HOME
|
||||
|
||||
if ! type cvs >/dev/null 2>&1
|
||||
then
|
||||
say 'skipping cvsimport tests, cvs not found'
|
||||
test_done
|
||||
fi
|
||||
|
||||
CVS="cvs -f"
|
||||
export CVS
|
||||
|
||||
cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'`
|
||||
case "$cvsps_version" in
|
||||
2.1 | 2.2*)
|
||||
;;
|
||||
'')
|
||||
say 'skipping cvsimport tests, cvsps not found'
|
||||
test_done
|
||||
;;
|
||||
*)
|
||||
say 'skipping cvsimport tests, unsupported cvsps version'
|
||||
test_done
|
||||
;;
|
||||
esac
|
||||
|
||||
test_cvs_co () {
|
||||
# Usage: test_cvs_co BRANCH_NAME
|
||||
rm -rf module-cvs-"$1"
|
||||
if [ "$1" = "master" ]
|
||||
then
|
||||
$CVS co -P -d module-cvs-"$1" -A module
|
||||
else
|
||||
$CVS co -P -d module-cvs-"$1" -r "$1" module
|
||||
fi
|
||||
}
|
||||
|
||||
test_git_co () {
|
||||
# Usage: test_git_co BRANCH_NAME
|
||||
(cd module-git && git checkout "$1")
|
||||
}
|
||||
|
||||
test_cmp_branch_file () {
|
||||
# Usage: test_cmp_branch_file BRANCH_NAME PATH
|
||||
# The branch must already be checked out of CVS and git.
|
||||
test_cmp module-cvs-"$1"/"$2" module-git/"$2"
|
||||
}
|
||||
|
||||
test_cmp_branch_tree () {
|
||||
# Usage: test_cmp_branch_tree BRANCH_NAME
|
||||
# Check BRANCH_NAME out of CVS and git and make sure that all
|
||||
# of the files and directories are identical.
|
||||
|
||||
test_cvs_co "$1" &&
|
||||
test_git_co "$1" &&
|
||||
(
|
||||
cd module-cvs-"$1"
|
||||
find . -type d -name CVS -prune -o -type f -print
|
||||
) | sort >module-cvs-"$1".list &&
|
||||
(
|
||||
cd module-git
|
||||
find . -type d -name .git -prune -o -type f -print
|
||||
) | sort >module-git-"$1".list &&
|
||||
test_cmp module-cvs-"$1".list module-git-"$1".list &&
|
||||
cat module-cvs-"$1".list | while read f
|
||||
do
|
||||
test_cmp_branch_file "$1" "$f" || return 1
|
||||
done
|
||||
}
|
||||
@@ -14,7 +14,7 @@ if ! test_have_prereq PERL; then
|
||||
fi
|
||||
|
||||
GIT_DIR=$PWD/.git
|
||||
GIT_SVN_DIR=$GIT_DIR/svn/git-svn
|
||||
GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
|
||||
SVN_TREE=$GIT_SVN_DIR/svn-tree
|
||||
|
||||
svn >/dev/null 2>&1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user