1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-11-17 22:44:49 +01:00

Merge branch 'js/fetchconfig' into next

* js/fetchconfig:
  Add a conversion tool to migrate remote information into the config
  fetch, pull: ask config for remote information
  Add a few more words to the glossary.
  Added definitions for a few words:
  Alphabetize the glossary.
  sha1_to_hex() usage cleanup
This commit is contained in:
Junio C Hamano 2006-05-04 00:14:56 -07:00
commit 4cc0b8a41b
11 changed files with 333 additions and 207 deletions

View file

@ -1,39 +1,71 @@
object:: alternate object database::
The unit of storage in git. It is uniquely identified by Via the alternates mechanism, a repository can inherit part of its
the SHA1 of its contents. Consequently, an object can not object database from another object database, which is called
be changed. "alternate".
object name:: bare repository::
The unique identifier of an object. The hash of the object's contents A bare repository is normally an appropriately named
using the Secure Hash Algorithm 1 and usually represented by the 40 directory with a `.git` suffix that does not have a
character hexadecimal encoding of the hash of the object (possibly locally checked-out copy of any of the files under revision
followed by a white space). control. That is, all of the `git` administrative and
control files that would normally be present in the
SHA1:: hidden `.git` sub-directory are directly present in
Synonym for object name. the `repository.git` directory instead, and no other files
are present and checked out. Usually publishers of public
object identifier:: repositories make bare repositories available.
Synonym for object name.
hash::
In git's context, synonym to object name.
object database::
Stores a set of "objects", and an individual object is identified
by its object name. The objects usually live in `$GIT_DIR/objects/`.
blob object:: blob object::
Untyped object, e.g. the contents of a file. Untyped object, e.g. the contents of a file.
tree object:: branch::
An object containing a list of file names and modes along with refs A non-cyclical graph of revisions, i.e. the complete history of
to the associated blob and/or tree objects. A tree is equivalent a particular revision, which is called the branch head. The
to a directory. branch heads are stored in `$GIT_DIR/refs/heads/`.
tree:: cache::
Either a working tree, or a tree object together with the Obsolete for: index.
dependent blob and tree objects (i.e. a stored representation
of a working tree). chain::
A list of objects, where each object in the list contains a
reference to its successor (for example, the successor of a commit
could be one of its parents).
changeset::
BitKeeper/cvsps speak for "commit". Since git does not store
changes, but states, it really does not make sense to use
the term "changesets" with git.
checkout::
The action of updating the working tree to a revision which was
stored in the object database.
cherry-picking::
In SCM jargon, "cherry pick" means to choose a subset of
changes out of a series of changes (typically commits)
and record them as a new series of changes on top of
different codebase. In GIT, this is performed by
"git cherry-pick" command to extract the change
introduced by an existing commit and to record it based
on the tip of the current branch as a new commit.
clean::
A working tree is clean, if it corresponds to the revision
referenced by the current head. Also see "dirty".
commit::
As a verb: The action of storing the current state of the index in the
object database. The result is a revision.
As a noun: Short hand for commit object.
commit object::
An object which contains the information about a particular
revision, such as parents, committer, author, date and the
tree object which corresponds to the top directory of the
stored revision.
core git::
Fundamental data structures and utilities of git. Exposes only
limited source code management tools.
DAG:: DAG::
Directed acyclic graph. The commit objects form a directed acyclic Directed acyclic graph. The commit objects form a directed acyclic
@ -41,6 +73,63 @@ DAG::
objects is acyclic (there is no chain which begins and ends with the objects is acyclic (there is no chain which begins and ends with the
same object). same object).
dircache::
You are *waaaaay* behind.
dirty::
A working tree is said to be dirty if it contains modifications
which have not been committed to the current branch.
directory::
The list you get with "ls" :-)
ent::
Favorite synonym to "tree-ish" by some total geeks. See
`http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth
explanation.
fast forward::
A fast-forward is a special type of merge where you have
a revision and you are "merging" another branch's changes
that happen to be a descendant of what you have.
In such these cases, you do not make a new merge commit but
instead just update to his revision. This will happen
frequently on a tracking branch of a remote repository.
fetch::
Fetching a branch means to get the branch's head ref from a
remote repository, to find out which objects are missing from
the local object database, and to get them, too.
file system::
Linus Torvalds originally designed git to be a user space file
system, i.e. the infrastructure to hold files and directories.
That ensured the efficiency and speed of git.
git archive::
Synonym for repository (for arch people).
hash::
In git's context, synonym to object name.
head::
The top of a branch. It contains a ref to the corresponding
commit object.
head ref::
A ref pointing to a head. Often, this is abbreviated to "head".
Head refs are stored in `$GIT_DIR/refs/heads/`.
hook::
During the normal execution of several git commands,
call-outs are made to optional scripts that allow
a developer to add functionality or checking.
Typically, the hooks allow for a command to be pre-verified
and potentially aborted, and allow for a post-notification
after the operation is done.
The hook scripts are found in the `$GIT_DIR/hooks/` directory,
and are enabled by simply making them executable.
index:: index::
A collection of files with stat information, whose contents are A collection of files with stat information, whose contents are
stored as objects. The index is a stored version of your working stored as objects. The index is a stored version of your working
@ -53,92 +142,167 @@ index entry::
yet finished (i.e. if the index contains multiple versions of yet finished (i.e. if the index contains multiple versions of
that file). that file).
unmerged index: master::
An index which contains unmerged index entries. The default development branch. Whenever you create a git
repository, a branch named "master" is created, and becomes
the active branch. In most cases, this contains the local
development, though that is purely conventional and not required.
cache:: merge::
Obsolete for: index. To merge branches means to try to accumulate the changes since a
common ancestor and apply them to the first branch. An automatic
merge uses heuristics to accomplish that. Evidently, an automatic
merge can fail.
working tree:: object::
The set of files and directories currently being worked on, The unit of storage in git. It is uniquely identified by
i.e. you can work in your working tree without using git at all. the SHA1 of its contents. Consequently, an object can not
be changed.
directory:: object database::
The list you get with "ls" :-) Stores a set of "objects", and an individual object is identified
by its object name. The objects usually live in `$GIT_DIR/objects/`.
revision:: object identifier::
A particular state of files and directories which was stored in Synonym for object name.
the object database. It is referenced by a commit object.
checkout:: object name::
The action of updating the working tree to a revision which was The unique identifier of an object. The hash of the object's contents
stored in the object database. using the Secure Hash Algorithm 1 and usually represented by the 40
character hexadecimal encoding of the hash of the object (possibly
followed by a white space).
commit:: object type:
As a verb: The action of storing the current state of the index in the One of the identifiers "commit","tree","tag" and "blob" describing
object database. The result is a revision. the type of an object.
As a noun: Short hand for commit object.
commit object:: octopus::
An object which contains the information about a particular To merge more than two branches. Also denotes an intelligent
revision, such as parents, committer, author, date and the predator.
tree object which corresponds to the top directory of the
stored revision. origin::
The default upstream tracking branch. Most projects have at
least one upstream project which they track. By default
'origin' is used for that purpose. New upstream updates
will be fetched into this branch; you should never commit
to it yourself.
pack::
A set of objects which have been compressed into one file (to save
space or to transmit them efficiently).
pack index::
The list of identifiers, and other information, of the objects in a
pack, to assist in efficiently accessing the contents of a pack.
parent:: parent::
A commit object contains a (possibly empty) list of the logical A commit object contains a (possibly empty) list of the logical
predecessor(s) in the line of development, i.e. its parents. predecessor(s) in the line of development, i.e. its parents.
changeset:: pickaxe::
BitKeeper/cvsps speak for "commit". Since git does not store The term pickaxe refers to an option to the diffcore routines
changes, but states, it really does not make sense to use that help select changes that add or delete a given text string.
the term "changesets" with git. With the --pickaxe-all option, it can be used to view the
full changeset that introduced or removed, say, a particular
line of text. See gitlink:git-diff[1].
clean:: plumbing::
A working tree is clean, if it corresponds to the revision Cute name for core git.
referenced by the current head.
dirty:: porcelain::
A working tree is said to be dirty if it contains modifications Cute name for programs and program suites depending on core git,
which have not been committed to the current branch. presenting a high level access to core git. Porcelains expose
more of a SCM interface than the plumbing.
head:: pull::
The top of a branch. It contains a ref to the corresponding Pulling a branch means to fetch it and merge it.
commit object.
branch:: push::
A non-cyclical graph of revisions, i.e. the complete history of Pushing a branch means to get the branch's head ref from a remote
a particular revision, which is called the branch head. The repository, find out if it is an ancestor to the branch's local
branch heads are stored in `$GIT_DIR/refs/heads/`. head ref is a direct, and in that case, putting all objects, which
are reachable from the local head ref, and which are missing from
the remote repository, into the remote object database, and updating
the remote head ref. If the remote head is not an ancestor to the
local head, the push fails.
master:: reachable::
The default branch. Whenever you create a git repository, a branch An object is reachable from a ref/commit/tree/tag, if there is a
named "master" is created, and becomes the active branch. In most chain leading from the latter to the former.
cases, this contains the local development.
origin:: rebase::
The default upstream branch. Most projects have one upstream To clean a branch by starting from the head of the main line of
project which they track, and by default 'origin' is used for development ("master"), and reapply the (possibly cherry-picked)
that purpose. New updates from upstream will be fetched into changes from that branch.
this branch; you should never commit to it yourself.
ref:: ref::
A 40-byte hex representation of a SHA1 pointing to a particular A 40-byte hex representation of a SHA1 or a name that denotes
object. These may be stored in `$GIT_DIR/refs/`. a particular object. These may be stored in `$GIT_DIR/refs/`.
head ref:: refspec::
A ref pointing to a head. Often, this is abbreviated to "head". A refspec is used by fetch and push to describe the mapping
Head refs are stored in `$GIT_DIR/refs/heads/`. between remote ref and local ref. They are combined with
a colon in the format <src>:<dst>, preceded by an optional
plus sign, +. For example:
`git fetch $URL refs/heads/master:refs/heads/origin`
means "grab the master branch head from the $URL and store
it as my origin branch head".
And `git push $URL refs/heads/master:refs/heads/to-upstream`
means "publish my master branch head as to-upstream master head
at $URL". See also gitlink:git-push[1]
repository::
A collection of refs together with an object database containing
all objects, which are reachable from the refs, possibly accompanied
by meta data from one or more porcelains. A repository can
share an object database with other repositories.
resolve::
The action of fixing up manually what a failed automatic merge
left behind.
revision::
A particular state of files and directories which was stored in
the object database. It is referenced by a commit object.
rewind::
To throw away part of the development, i.e. to assign the head to
an earlier revision.
SCM::
Source code management (tool).
SHA1::
Synonym for object name.
topic branch::
A regular git branch that is used by a developer to
identify a conceptual line of development. Since branches
are very easy and inexpensive, it is often desirable to
have several small branches that each contain very well
defined concepts or small incremental yet related changes.
tracking branch::
A regular git branch that is used to follow changes from
another repository. A tracking branch should not contain
direct modifications or have local commits made to it.
A tracking branch can usually be identified as the
right-hand-side ref in a Pull: refspec.
tree object::
An object containing a list of file names and modes along with refs
to the associated blob and/or tree objects. A tree is equivalent
to a directory.
tree::
Either a working tree, or a tree object together with the
dependent blob and tree objects (i.e. a stored representation
of a working tree).
tree-ish:: tree-ish::
A ref pointing to either a commit object, a tree object, or a A ref pointing to either a commit object, a tree object, or a
tag object pointing to a tag or commit or tree object. tag object pointing to a tag or commit or tree object.
ent::
Favorite synonym to "tree-ish" by some total geeks. See
`http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth
explanation.
tag object:: tag object::
An object containing a ref pointing to another object, which can An object containing a ref pointing to another object, which can
contain a message just like a commit object. It can also contain a message just like a commit object. It can also
@ -153,101 +317,10 @@ tag::
A tag is most typically used to mark a particular point in the A tag is most typically used to mark a particular point in the
commit ancestry chain. commit ancestry chain.
merge:: unmerged index:
To merge branches means to try to accumulate the changes since a An index which contains unmerged index entries.
common ancestor and apply them to the first branch. An automatic
merge uses heuristics to accomplish that. Evidently, an automatic
merge can fail.
octopus:: working tree::
To merge more than two branches. Also denotes an intelligent The set of files and directories currently being worked on,
predator. i.e. you can work in your working tree without using git at all.
resolve::
The action of fixing up manually what a failed automatic merge
left behind.
rewind::
To throw away part of the development, i.e. to assign the head to
an earlier revision.
rebase::
To clean a branch by starting from the head of the main line of
development ("master"), and reapply the (possibly cherry-picked)
changes from that branch.
repository::
A collection of refs together with an object database containing
all objects, which are reachable from the refs, possibly accompanied
by meta data from one or more porcelains. A repository can
share an object database with other repositories.
git archive::
Synonym for repository (for arch people).
file system::
Linus Torvalds originally designed git to be a user space file
system, i.e. the infrastructure to hold files and directories.
That ensured the efficiency and speed of git.
alternate object database::
Via the alternates mechanism, a repository can inherit part of its
object database from another object database, which is called
"alternate".
reachable::
An object is reachable from a ref/commit/tree/tag, if there is a
chain leading from the latter to the former.
chain::
A list of objects, where each object in the list contains a
reference to its successor (for example, the successor of a commit
could be one of its parents).
fetch::
Fetching a branch means to get the branch's head ref from a
remote repository, to find out which objects are missing from
the local object database, and to get them, too.
pull::
Pulling a branch means to fetch it and merge it.
push::
Pushing a branch means to get the branch's head ref from a remote
repository, find out if it is an ancestor to the branch's local
head ref is a direct, and in that case, putting all objects, which
are reachable from the local head ref, and which are missing from
the remote repository, into the remote object database, and updating
the remote head ref. If the remote head is not an ancestor to the
local head, the push fails.
pack::
A set of objects which have been compressed into one file (to save
space or to transmit them efficiently).
pack index::
The list of identifiers, and other information, of the objects in a
pack, to assist in efficiently accessing the contents of a pack.
core git::
Fundamental data structures and utilities of git. Exposes only
limited source code management tools.
plumbing::
Cute name for core git.
porcelain::
Cute name for programs and program suites depending on core git,
presenting a high level access to core git. Porcelains expose
more of a SCM interface than the plumbing.
object type:
One of the identifiers "commit","tree","tag" and "blob" describing
the type of an object.
SCM::
Source code management (tool).
dircache::
You are *waaaaay* behind.

View file

@ -48,7 +48,7 @@ ($)
'; ';
@keys=sort {uc($a) cmp uc($b)} keys %terms; @keys=sort {uc($a) cmp uc($b)} keys %terms;
$pattern='(\b'.join('\b|\b',reverse @keys).'\b)'; $pattern='(\b(?<!link:git-)'.join('\b|\b(?<!link:git-)',reverse @keys).'\b)';
foreach $key (@keys) { foreach $key (@keys) {
$terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg; $terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg;
print '[[ref_'.no_spaces($key).']]'.$key."::\n" print '[[ref_'.no_spaces($key).']]'.$key."::\n"

View file

@ -215,8 +215,8 @@ LIB_OBJS = \
$(DIFF_OBJS) $(DIFF_OBJS)
BUILTIN_OBJS = \ BUILTIN_OBJS = \
builtin-log.o builtin-help.o builtin-count.o builtin-diff.o \ builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \
builtin-push.o builtin-grep.o builtin-grep.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB) GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz LIBS = $(GITLIBS) -lz

View file

@ -271,7 +271,7 @@ int cmd_diff(int argc, const char **argv, char **envp)
* *
* Other cases are errors. * Other cases are errors.
*/ */
git_config(git_diff_config); git_config(git_diff_config);
init_revisions(&rev); init_revisions(&rev);
rev.diffopt.output_format = DIFF_FORMAT_PATCH; rev.diffopt.output_format = DIFF_FORMAT_PATCH;
@ -321,7 +321,7 @@ int cmd_diff(int argc, const char **argv, char **envp)
blob[blobs].name = name; blob[blobs].name = name;
blobs++; blobs++;
continue; continue;
} }
die("unhandled object '%s' given.", name); die("unhandled object '%s' given.", name);
} }

View file

@ -19,9 +19,10 @@ extern int cmd_version(int argc, const char **argv, char **envp);
extern int cmd_whatchanged(int argc, const char **argv, char **envp); extern int cmd_whatchanged(int argc, const char **argv, char **envp);
extern int cmd_show(int argc, const char **argv, char **envp); extern int cmd_show(int argc, const char **argv, char **envp);
extern int cmd_log(int argc, const char **argv, char **envp); extern int cmd_log(int argc, const char **argv, char **envp);
extern int cmd_diff(int argc, const char **argv, char **envp);
extern int cmd_format_patch(int argc, const char **argv, char **envp); extern int cmd_format_patch(int argc, const char **argv, char **envp);
extern int cmd_count_objects(int argc, const char **argv, char **envp); extern int cmd_count_objects(int argc, const char **argv, char **envp);
extern int cmd_diff(int argc, const char **argv, char **envp);
extern int cmd_push(int argc, const char **argv, char **envp); extern int cmd_push(int argc, const char **argv, char **envp);
extern int cmd_grep(int argc, const char **argv, char **envp); extern int cmd_grep(int argc, const char **argv, char **envp);

35
contrib/remotes2config.sh Normal file
View file

@ -0,0 +1,35 @@
#!/bin/sh
# Use this tool to rewrite your .git/remotes/ files into the config.
. git-sh-setup
if [ -d "$GIT_DIR"/remotes ]; then
echo "Rewriting $GIT_DIR/remotes" >&2
error=0
# rewrite into config
{
cd "$GIT_DIR"/remotes
ls | while read f; do
name=$(echo -n "$f" | tr -c "A-Za-z0-9" ".")
sed -n \
-e "s/^URL: \(.*\)$/remote.$name.url \1 ./p" \
-e "s/^Pull: \(.*\)$/remote.$name.fetch \1 ^$ /p" \
-e "s/^Push: \(.*\)$/remote.$name.push \1 ^$ /p" \
< "$f"
done
echo done
} | while read key value regex; do
case $key in
done)
if [ $error = 0 ]; then
mv "$GIT_DIR"/remotes "$GIT_DIR"/remotes.old
fi ;;
*)
echo "git-repo-config $key "$value" $regex"
git-repo-config $key "$value" $regex || error=1 ;;
esac
done
fi

6
diff.c
View file

@ -1018,14 +1018,12 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
} }
if (memcmp(one->sha1, two->sha1, 20)) { if (memcmp(one->sha1, two->sha1, 20)) {
char one_sha1[41];
int abbrev = o->full_index ? 40 : DEFAULT_ABBREV; int abbrev = o->full_index ? 40 : DEFAULT_ABBREV;
memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
len += snprintf(msg + len, sizeof(msg) - len, len += snprintf(msg + len, sizeof(msg) - len,
"index %.*s..%.*s", "index %.*s..%.*s",
abbrev, one_sha1, abbrev, abbrev, sha1_to_hex(one->sha1),
sha1_to_hex(two->sha1)); abbrev, sha1_to_hex(two->sha1));
if (one->mode == two->mode) if (one->mode == two->mode)
len += snprintf(msg + len, sizeof(msg) - len, len += snprintf(msg + len, sizeof(msg) - len,
" %06o", one->mode); " %06o", one->mode);

View file

@ -10,7 +10,10 @@ get_data_source () {
# Not so fast. This could be the partial URL shorthand... # Not so fast. This could be the partial URL shorthand...
token=$(expr "z$1" : 'z\([^/]*\)/') token=$(expr "z$1" : 'z\([^/]*\)/')
remainder=$(expr "z$1" : 'z[^/]*/\(.*\)') remainder=$(expr "z$1" : 'z[^/]*/\(.*\)')
if test -f "$GIT_DIR/branches/$token" if test "$(git-repo-config --get "remote.$token.url")"
then
echo config-partial
elif test -f "$GIT_DIR/branches/$token"
then then
echo branches-partial echo branches-partial
else else
@ -18,7 +21,10 @@ get_data_source () {
fi fi
;; ;;
*) *)
if test -f "$GIT_DIR/remotes/$1" if test "$(git-repo-config --get "remote.$1.url")"
then
echo config
elif test -f "$GIT_DIR/remotes/$1"
then then
echo remotes echo remotes
elif test -f "$GIT_DIR/branches/$1" elif test -f "$GIT_DIR/branches/$1"
@ -35,6 +41,15 @@ get_remote_url () {
case "$data_source" in case "$data_source" in
'') '')
echo "$1" ;; echo "$1" ;;
config-partial)
token=$(expr "z$1" : 'z\([^/]*\)/')
remainder=$(expr "z$1" : 'z[^/]*/\(.*\)')
url=$(git-repo-config --get "remote.$token.url")
echo "$url/$remainder"
;;
config)
git-repo-config --get "remote.$1.url"
;;
remotes) remotes)
sed -ne '/^URL: */{ sed -ne '/^URL: */{
s///p s///p
@ -56,8 +71,10 @@ get_remote_url () {
get_remote_default_refs_for_push () { get_remote_default_refs_for_push () {
data_source=$(get_data_source "$1") data_source=$(get_data_source "$1")
case "$data_source" in case "$data_source" in
'' | branches | branches-partial) '' | config-partial | branches | branches-partial)
;; # no default push mapping, just send matching refs. ;; # no default push mapping, just send matching refs.
config)
git-repo-config --get-all "remote.$1.push" ;;
remotes) remotes)
sed -ne '/^Push: */{ sed -ne '/^Push: */{
s///p s///p
@ -111,8 +128,11 @@ canon_refs_list_for_fetch () {
get_remote_default_refs_for_fetch () { get_remote_default_refs_for_fetch () {
data_source=$(get_data_source "$1") data_source=$(get_data_source "$1")
case "$data_source" in case "$data_source" in
'' | branches-partial) '' | config-partial | branches-partial)
echo "HEAD:" ;; echo "HEAD:" ;;
config)
canon_refs_list_for_fetch \
$(git-repo-config --get-all "remote.$1.fetch") ;;
branches) branches)
remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1") remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
case "$remote_branch" in '') remote_branch=master ;; esac case "$remote_branch" in '') remote_branch=master ;; esac

2
git.c
View file

@ -46,10 +46,10 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "log", cmd_log }, { "log", cmd_log },
{ "whatchanged", cmd_whatchanged }, { "whatchanged", cmd_whatchanged },
{ "show", cmd_show }, { "show", cmd_show },
{ "push", cmd_push },
{ "fmt-patch", cmd_format_patch }, { "fmt-patch", cmd_format_patch },
{ "count-objects", cmd_count_objects }, { "count-objects", cmd_count_objects },
{ "diff", cmd_diff }, { "diff", cmd_diff },
{ "push", cmd_push },
{ "grep", cmd_grep }, { "grep", cmd_grep },
}; };
int i; int i;

View file

@ -24,16 +24,14 @@ static const char *sha1_to_hex_zero(const unsigned char *sha1)
static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result) static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result)
{ {
char branch1_sha1[50];
/* If it's already branch1, don't bother showing it */ /* If it's already branch1, don't bother showing it */
if (!branch1) if (!branch1)
return; return;
memcpy(branch1_sha1, sha1_to_hex_zero(branch1->sha1), 41);
printf("0 %06o->%06o %s->%s %s%s\n", printf("0 %06o->%06o %s->%s %s%s\n",
branch1->mode, result->mode, branch1->mode, result->mode,
branch1_sha1, sha1_to_hex_zero(result->sha1), sha1_to_hex_zero(branch1->sha1),
sha1_to_hex_zero(result->sha1),
base, result->path); base, result->path);
} }

View file

@ -108,9 +108,10 @@ int safe_create_leading_directories(char *path)
char * sha1_to_hex(const unsigned char *sha1) char * sha1_to_hex(const unsigned char *sha1)
{ {
static char buffer[50]; static int bufno;
static char hexbuffer[4][50];
static const char hex[] = "0123456789abcdef"; static const char hex[] = "0123456789abcdef";
char *buf = buffer; char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
int i; int i;
for (i = 0; i < 20; i++) { for (i = 0; i < 20; i++) {