Merge branches 'bf/doc' and 'db/tartree'
This commit is contained in:
commit
1a5c3a01aa
@ -1623,123 +1623,7 @@ suggested in the previous section may be new to you. You do not
|
|||||||
have to worry. git supports "shared public repository" style of
|
have to worry. git supports "shared public repository" style of
|
||||||
cooperation you are probably more familiar with as well.
|
cooperation you are probably more familiar with as well.
|
||||||
|
|
||||||
For this, set up a public repository on a machine that is
|
See link:cvs-migration.txt[git for CVS users] for the details.
|
||||||
reachable via SSH by people with "commit privileges". Put the
|
|
||||||
committers in the same user group and make the repository
|
|
||||||
writable by that group. Make sure their umasks are set up to
|
|
||||||
allow group members to write into directories other members
|
|
||||||
have created.
|
|
||||||
|
|
||||||
You, as an individual committer, then:
|
|
||||||
|
|
||||||
- First clone the shared repository to a local repository:
|
|
||||||
------------------------------------------------
|
|
||||||
$ git clone repo.shared.xz:/pub/scm/project.git/ my-project
|
|
||||||
$ cd my-project
|
|
||||||
$ hack away
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
- Merge the work others might have done while you were hacking
|
|
||||||
away:
|
|
||||||
------------------------------------------------
|
|
||||||
$ git pull origin
|
|
||||||
$ test the merge result
|
|
||||||
------------------------------------------------
|
|
||||||
[NOTE]
|
|
||||||
================================
|
|
||||||
The first `git clone` would have placed the following in
|
|
||||||
`my-project/.git/remotes/origin` file, and that's why this and
|
|
||||||
the next step work.
|
|
||||||
------------
|
|
||||||
URL: repo.shared.xz:/pub/scm/project.git/ my-project
|
|
||||||
Pull: master:origin
|
|
||||||
------------
|
|
||||||
================================
|
|
||||||
|
|
||||||
- push your work as the new head of the shared
|
|
||||||
repository.
|
|
||||||
------------------------------------------------
|
|
||||||
$ git push origin master
|
|
||||||
------------------------------------------------
|
|
||||||
If somebody else pushed into the same shared repository while
|
|
||||||
you were working locally, `git push` in the last step would
|
|
||||||
complain, telling you that the remote `master` head does not
|
|
||||||
fast forward. You need to pull and merge those other changes
|
|
||||||
back before you push your work when it happens.
|
|
||||||
|
|
||||||
The `git push` command without any explicit refspec parameter
|
|
||||||
pushes the refs that exist both in the local repository and the
|
|
||||||
remote repository. So the last `push` can be done with either
|
|
||||||
one of these:
|
|
||||||
------------
|
|
||||||
$ git push origin
|
|
||||||
$ git push repo.shared.xz:/pub/scm/project.git/
|
|
||||||
------------
|
|
||||||
as long as the shared repository does not have any branches
|
|
||||||
other than `master`.
|
|
||||||
[NOTE]
|
|
||||||
============
|
|
||||||
If you created your shared repository by cloning from somewhere
|
|
||||||
else, you may have the `origin` branch. Your developers
|
|
||||||
typically do not use that branch; remove it. Otherwise, that
|
|
||||||
would be pushed back by the `git push origin` because your
|
|
||||||
developers' repository would surely have `origin` branch to keep
|
|
||||||
track of the shared repository, and would be counted as "exist
|
|
||||||
on both ends".
|
|
||||||
============
|
|
||||||
|
|
||||||
Advanced Shared Repository Management
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
Being able to push into a shared repository means being able to
|
|
||||||
write into it. If your developers are coming over the network,
|
|
||||||
this means you, as the repository administrator, need to give
|
|
||||||
each of them an SSH access to the shared repository machine.
|
|
||||||
|
|
||||||
In some cases, though, you may not want to give a normal shell
|
|
||||||
account to them, but want to restrict them to be able to only
|
|
||||||
do `git push` into the repository and nothing else.
|
|
||||||
|
|
||||||
You can achieve this by setting the login shell of your
|
|
||||||
developers on the shared repository host to `git-shell` program.
|
|
||||||
|
|
||||||
[NOTE]
|
|
||||||
Most likely you would also need to list `git-shell` program in
|
|
||||||
`/etc/shells` file.
|
|
||||||
|
|
||||||
This restricts the set of commands that can be run from incoming
|
|
||||||
SSH connection for these users to only `receive-pack` and
|
|
||||||
`upload-pack`, so the only thing they can do are `git fetch` and
|
|
||||||
`git push`.
|
|
||||||
|
|
||||||
You still need to create UNIX user accounts for each developer,
|
|
||||||
and put them in the same group. Make sure that the repository
|
|
||||||
shared among these developers is writable by that group.
|
|
||||||
|
|
||||||
. Initializing the shared repository with `git-init-db --shared`
|
|
||||||
helps somewhat.
|
|
||||||
|
|
||||||
. Run the following in the shared repository:
|
|
||||||
+
|
|
||||||
------------
|
|
||||||
$ chgrp -R $group repo.git
|
|
||||||
$ find repo.git -type d -print | xargs chmod ug+rwx,g+s
|
|
||||||
$ GIT_DIR=repo.git git repo-config core.sharedrepository true
|
|
||||||
------------
|
|
||||||
|
|
||||||
The above measures make sure that directories lazily created in
|
|
||||||
`$GIT_DIR` are writable by group members. You, as the
|
|
||||||
repository administrator, are still responsible to make sure
|
|
||||||
your developers belong to that shared repository group and set
|
|
||||||
their umask to a value no stricter than 027 (i.e. at least allow
|
|
||||||
reading and searching by group members).
|
|
||||||
|
|
||||||
You can implement finer grained branch policies using update
|
|
||||||
hooks. There is a document ("control access to branches") in
|
|
||||||
Documentation/howto by Carl Baldwin and JC outlining how to (1)
|
|
||||||
limit access to branch per user, (2) forbid overwriting existing
|
|
||||||
tags.
|
|
||||||
|
|
||||||
|
|
||||||
Bundling your work together
|
Bundling your work together
|
||||||
---------------------------
|
---------------------------
|
||||||
|
@ -1,126 +1,182 @@
|
|||||||
git for CVS users
|
git for CVS users
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Ok, so you're a CVS user. That's ok, it's a treatable condition, and the
|
So you're a CVS user. That's ok, it's a treatable condition. The job of
|
||||||
first step to recovery is admitting you have a problem. The fact that
|
this document is to put you on the road to recovery, by helping you
|
||||||
you are reading this file means that you may be well on that path
|
convert an existing cvs repository to git, and by showing you how to use a
|
||||||
already.
|
git repository in a cvs-like fashion.
|
||||||
|
|
||||||
The thing about CVS is that it absolutely sucks as a source control
|
Some basic familiarity with git is required. This
|
||||||
manager, and you'll thus be happy with almost anything else. git,
|
link:tutorial.html[tutorial introduction to git] should be sufficient.
|
||||||
however, may be a bit 'too' different (read: "good") for your taste, and
|
|
||||||
does a lot of things differently.
|
|
||||||
|
|
||||||
One particular suckage of CVS is very hard to work around: CVS is
|
First, note some ways that git differs from CVS:
|
||||||
basically a tool for tracking 'file' history, while git is a tool for
|
|
||||||
tracking 'project' history. This sometimes causes problems if you are
|
|
||||||
used to doing very strange things in CVS, in particular if you're doing
|
|
||||||
things like making branches of just a subset of the project. git can't
|
|
||||||
track that, since git never tracks things on the level of an individual
|
|
||||||
file, only on the whole project level.
|
|
||||||
|
|
||||||
The good news is that most people don't do that, and in fact most sane
|
* Commits are atomic and project-wide, not per-file as in CVS.
|
||||||
people think it's a bug in CVS that makes it tag (and check in changes)
|
|
||||||
one file at a time. So most projects you'll ever see will use CVS
|
|
||||||
'as if' it was sane. In which case you'll find it very easy indeed to
|
|
||||||
move over to git.
|
|
||||||
|
|
||||||
First off: this is not a git tutorial. See
|
* Offline work is supported: you can make multiple commits locally,
|
||||||
link:tutorial.html[Documentation/tutorial.txt] for how git
|
then submit them when you're ready.
|
||||||
actually works. This is more of a random collection of gotcha's
|
|
||||||
and notes on converting from CVS to git.
|
|
||||||
|
|
||||||
Second: CVS has the notion of a "repository" as opposed to the thing
|
* Branching is fast and easy.
|
||||||
that you're actually working in (your working directory, or your
|
|
||||||
"checked out tree"). git does not have that notion at all, and all git
|
|
||||||
working directories 'are' the repositories. However, you can easily
|
|
||||||
emulate the CVS model by having one special "global repository", which
|
|
||||||
people can synchronize with. See details later, but in the meantime
|
|
||||||
just keep in mind that with git, every checked out working tree will
|
|
||||||
have a full revision control history of its own.
|
|
||||||
|
|
||||||
|
* Every working tree contains a repository with a full copy of the
|
||||||
|
project history, and no repository is inherently more important than
|
||||||
|
any other. However, you can emulate the CVS model by designating a
|
||||||
|
single shared repository which people can synchronize with; see below
|
||||||
|
for details.
|
||||||
|
|
||||||
Importing a CVS archive
|
Importing a CVS archive
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Ok, you have an old project, and you want to at least give git a chance
|
First, install version 2.1 or higher of cvsps from
|
||||||
to see how it performs. The first thing you want to do (after you've
|
link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make
|
||||||
gone through the git tutorial, and generally familiarized yourself with
|
sure it is in your path. The magic command line is then
|
||||||
how to commit stuff etc in git) is to create a git'ified version of your
|
|
||||||
CVS archive.
|
|
||||||
|
|
||||||
Happily, that's very easy indeed. git will do it for you, although git
|
-------------------------------------------
|
||||||
will need the help of a program called "cvsps":
|
$ git cvsimport -v -d <cvsroot> -C <destination> <module>
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
http://www.cobite.com/cvsps/
|
This puts a git archive of the named CVS module in the directory
|
||||||
|
<destination>, which will be created if necessary. The -v option makes
|
||||||
|
the conversion script very chatty.
|
||||||
|
|
||||||
which is not actually related to git at all, but which makes CVS usage
|
The import checks out from CVS every revision of every file. Reportedly
|
||||||
look almost sane (ie you almost certainly want to have it even if you
|
cvsimport can average some twenty revisions per second, so for a
|
||||||
decide to stay with CVS). However, git will want 'at least' version 2.1
|
medium-sized project this should not take more than a couple of minutes.
|
||||||
of cvsps (available at the address above), and in fact will currently
|
Larger projects or remote repositories may take longer.
|
||||||
refuse to work with anything else.
|
|
||||||
|
|
||||||
Once you've gotten (and installed) cvsps, you may or may not want to get
|
The main trunk is stored in the git branch named `origin`, and additional
|
||||||
any more familiar with it, but make sure it is in your path. After that,
|
CVS branches are stored in git branches with the same names. The most
|
||||||
the magic command line is
|
recent version of the main trunk is also left checked out on the `master`
|
||||||
|
branch, so you can start adding your own changes right away.
|
||||||
|
|
||||||
git cvsimport -v -d <cvsroot> -C <destination> <module>
|
The import is incremental, so if you call it again next month it will
|
||||||
|
fetch any CVS updates that have been made in the meantime. For this to
|
||||||
|
work, you must not modify the imported branches; instead, create new
|
||||||
|
branches for your own changes, and merge in the imported branches as
|
||||||
|
necessary.
|
||||||
|
|
||||||
which will do exactly what you'd think it does: it will create a git
|
Development Models
|
||||||
archive of the named CVS module. The new archive will be created in the
|
------------------
|
||||||
subdirectory named <destination>; it'll be created if it doesn't exist.
|
|
||||||
Default is the local directory.
|
|
||||||
|
|
||||||
It can take some time to actually do the conversion for a large archive
|
CVS users are accustomed to giving a group of developers commit access to
|
||||||
since it involves checking out from CVS every revision of every file,
|
a common repository. In the next section we'll explain how to do this
|
||||||
and the conversion script is reasonably chatty unless you omit the '-v'
|
with git. However, the distributed nature of git allows other development
|
||||||
option, but on some not very scientific tests it averaged about twenty
|
models, and you may want to first consider whether one of them might be a
|
||||||
revisions per second, so a medium-sized project should not take more
|
better fit for your project.
|
||||||
than a couple of minutes. For larger projects or remote repositories,
|
|
||||||
the process may take longer.
|
|
||||||
|
|
||||||
After the (initial) import is done, the CVS archive's current head
|
For example, you can choose a single person to maintain the project's
|
||||||
revision will be checked out -- thus, you can start adding your own
|
primary public repository. Other developers then clone this repository
|
||||||
changes right away.
|
and each work in their own clone. When they have a series of changes that
|
||||||
|
they're happy with, they ask the maintainer to pull from the branch
|
||||||
|
containing the changes. The maintainer reviews their changes and pulls
|
||||||
|
them into the primary repository, which other developers pull from as
|
||||||
|
necessary to stay coordinated. The Linux kernel and other projects use
|
||||||
|
variants of this model.
|
||||||
|
|
||||||
The import is incremental, i.e. if you call it again next month it'll
|
With a small group, developers may just pull changes from each other's
|
||||||
fetch any CVS updates that have been happening in the meantime. The
|
repositories without the need for a central maintainer.
|
||||||
cut-off is date-based, so don't change the branches that were imported
|
|
||||||
from CVS.
|
|
||||||
|
|
||||||
You can merge those updates (or, in fact, a different CVS branch) into
|
Emulating the CVS Development Model
|
||||||
your main branch:
|
-----------------------------------
|
||||||
|
|
||||||
git resolve HEAD origin "merge with current CVS HEAD"
|
Start with an ordinary git working directory containing the project, and
|
||||||
|
remove the checked-out files, keeping just the bare .git directory:
|
||||||
|
|
||||||
The HEAD revision from CVS is named "origin", not "HEAD", because git
|
------------------------------------------------
|
||||||
already uses "HEAD". (If you don't like 'origin', use cvsimport's
|
$ mv project/.git /pub/repo.git
|
||||||
'-o' option to change it.)
|
$ rm -r project/
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
Next, give every team member read/write access to this repository. One
|
||||||
|
easy way to do this is to give all the team members ssh access to the
|
||||||
|
machine where the repository is hosted. If you don't want to give them a
|
||||||
|
full shell on the machine, there is a restricted shell which only allows
|
||||||
|
users to do git pushes and pulls; see gitlink:git-shell[1].
|
||||||
|
|
||||||
Emulating CVS behaviour
|
Put all the committers should in the same group, and make the repository
|
||||||
-----------------------
|
writable by that group:
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
$ chgrp -R $group repo.git
|
||||||
|
$ find repo.git -mindepth 1 -type d |xargs chmod ug+rwx,g+s
|
||||||
|
$ GIT_DIR=repo.git git repo-config core.sharedrepository true
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
So, by now you are convinced you absolutely want to work with git, but
|
Make sure committers have a umask of at most 027, so that the directories
|
||||||
at the same time you absolutely have to have a central repository.
|
they create are writable and searchable by other group members.
|
||||||
Step back and think again. Okay, you still need a single central
|
|
||||||
repository? There are several ways to go about that:
|
|
||||||
|
|
||||||
1. Designate a person responsible to pull all branches. Make the
|
Suppose this repository is now set up in /pub/repo.git on the host
|
||||||
repository of this person public, and make every team member
|
foo.com. Then as an individual commiter you can clone the shared
|
||||||
pull regularly from it.
|
repository:
|
||||||
|
|
||||||
2. Set up a public repository with read/write access for every team
|
------------------------------------------------
|
||||||
member. Use "git pull/push" as you used "cvs update/commit". Be
|
$ git clone foo.com:/pub/repo.git/ my-project
|
||||||
sure that your repository is up to date before pushing, just
|
$ cd my-project
|
||||||
like you used to do with "cvs commit"; your push will fail if
|
------------------------------------------------
|
||||||
what you are pushing is not up to date.
|
|
||||||
|
|
||||||
3. Make the repository of every team member public. It is the
|
and hack away. The equivalent of `cvs update` is
|
||||||
responsibility of each single member to pull from every other
|
|
||||||
team member.
|
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
$ git pull origin
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
which merges in any work that others might have done since the clone
|
||||||
|
operation.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
================================
|
||||||
|
The first `git clone` places the following in the
|
||||||
|
`my-project/.git/remotes/origin` file, and that's why the previous step
|
||||||
|
and the next step both work.
|
||||||
|
------------
|
||||||
|
URL: foo.com:/pub/project.git/ my-project
|
||||||
|
Pull: master:origin
|
||||||
|
------------
|
||||||
|
================================
|
||||||
|
|
||||||
|
You can update the shared repository with your changes using:
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
$ git push origin master
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
If someone else has updated the repository more recently, `git push`, like
|
||||||
|
`cvs commit`, will complain, in which case you must pull any changes
|
||||||
|
before attempting the push again.
|
||||||
|
|
||||||
|
In the `git push` command above we specify the name of the remote branch
|
||||||
|
to update (`master`). If we leave that out, `git push` tries to update
|
||||||
|
any branches in the remote repository that have the same name as a branch
|
||||||
|
in the local repository. So the last `push` can be done with either of:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git push origin
|
||||||
|
$ git push repo.shared.xz:/pub/scm/project.git/
|
||||||
|
------------
|
||||||
|
|
||||||
|
as long as the shared repository does not have any branches
|
||||||
|
other than `master`.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
============
|
||||||
|
Because of this behaviour, if the shared repository and the developer's
|
||||||
|
repository both have branches named `origin`, then a push like the above
|
||||||
|
attempts to update the `origin` branch in the shared repository from the
|
||||||
|
developer's `origin` branch. The results may be unexpected, so it's
|
||||||
|
usually best to remove any branch named `origin` from the shared
|
||||||
|
repository.
|
||||||
|
============
|
||||||
|
|
||||||
|
Advanced Shared Repository Management
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Git allows you to specify scripts called "hooks" to be run at certain
|
||||||
|
points. You can use these, for example, to send all commits to the shared
|
||||||
|
repository to a mailing list. See link:hooks.txt[Hooks used by git].
|
||||||
|
|
||||||
|
You can enforce finer grained permissions using update hooks. See
|
||||||
|
link:howto/update-hook-example.txt[Controlling access to branches using
|
||||||
|
update hooks].
|
||||||
|
|
||||||
CVS annotate
|
CVS annotate
|
||||||
------------
|
------------
|
||||||
|
89
tar-tree.c
89
tar-tree.c
@ -3,6 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "tree.h"
|
||||||
|
#include "commit.h"
|
||||||
|
|
||||||
#define RECORDSIZE (512)
|
#define RECORDSIZE (512)
|
||||||
#define BLOCKSIZE (RECORDSIZE * 20)
|
#define BLOCKSIZE (RECORDSIZE * 20)
|
||||||
@ -334,76 +336,45 @@ static void write_header(const unsigned char *sha1, char typeflag, const char *b
|
|||||||
write_if_needed();
|
write_if_needed();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void traverse_tree(void *buffer, unsigned long size,
|
static void traverse_tree(struct tree *tree,
|
||||||
struct path_prefix *prefix)
|
struct path_prefix *prefix)
|
||||||
{
|
{
|
||||||
struct path_prefix this_prefix;
|
struct path_prefix this_prefix;
|
||||||
|
struct tree_entry_list *item;
|
||||||
this_prefix.prev = prefix;
|
this_prefix.prev = prefix;
|
||||||
|
|
||||||
while (size) {
|
parse_tree(tree);
|
||||||
int namelen = strlen(buffer)+1;
|
item = tree->entries;
|
||||||
|
|
||||||
|
while (item) {
|
||||||
void *eltbuf;
|
void *eltbuf;
|
||||||
char elttype[20];
|
char elttype[20];
|
||||||
unsigned long eltsize;
|
unsigned long eltsize;
|
||||||
unsigned char *sha1 = buffer + namelen;
|
|
||||||
char *path = strchr(buffer, ' ') + 1;
|
|
||||||
unsigned int mode;
|
|
||||||
|
|
||||||
if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1)
|
eltbuf = read_sha1_file(item->item.any->sha1,
|
||||||
die("corrupt 'tree' file");
|
elttype, &eltsize);
|
||||||
if (S_ISDIR(mode) || S_ISREG(mode))
|
|
||||||
mode |= (mode & 0100) ? 0777 : 0666;
|
|
||||||
buffer = sha1 + 20;
|
|
||||||
size -= namelen + 20;
|
|
||||||
|
|
||||||
eltbuf = read_sha1_file(sha1, elttype, &eltsize);
|
|
||||||
if (!eltbuf)
|
if (!eltbuf)
|
||||||
die("cannot read %s", sha1_to_hex(sha1));
|
die("cannot read %s",
|
||||||
write_header(sha1, TYPEFLAG_AUTO, basedir, prefix, path,
|
sha1_to_hex(item->item.any->sha1));
|
||||||
mode, eltbuf, eltsize);
|
write_header(item->item.any->sha1, TYPEFLAG_AUTO, basedir,
|
||||||
if (!strcmp(elttype, "tree")) {
|
prefix, item->name,
|
||||||
this_prefix.name = path;
|
item->mode, eltbuf, eltsize);
|
||||||
traverse_tree(eltbuf, eltsize, &this_prefix);
|
if (item->directory) {
|
||||||
} else if (!strcmp(elttype, "blob") && !S_ISLNK(mode)) {
|
this_prefix.name = item->name;
|
||||||
|
traverse_tree(item->item.tree, &this_prefix);
|
||||||
|
} else if (!item->symlink) {
|
||||||
write_blocked(eltbuf, eltsize);
|
write_blocked(eltbuf, eltsize);
|
||||||
}
|
}
|
||||||
free(eltbuf);
|
free(eltbuf);
|
||||||
|
item = item->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get commit time from committer line of commit object */
|
|
||||||
static time_t commit_time(void * buffer, unsigned long size)
|
|
||||||
{
|
|
||||||
time_t result = 0;
|
|
||||||
char *p = buffer;
|
|
||||||
|
|
||||||
while (size > 0) {
|
|
||||||
char *endp = memchr(p, '\n', size);
|
|
||||||
if (!endp || endp == p)
|
|
||||||
break;
|
|
||||||
*endp = '\0';
|
|
||||||
if (endp - p > 10 && !memcmp(p, "committer ", 10)) {
|
|
||||||
char *nump = strrchr(p, '>');
|
|
||||||
if (!nump)
|
|
||||||
break;
|
|
||||||
nump++;
|
|
||||||
result = strtoul(nump, &endp, 10);
|
|
||||||
if (*endp != ' ')
|
|
||||||
result = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
size -= endp - p - 1;
|
|
||||||
p = endp + 1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
unsigned char commit_sha1[20];
|
struct commit *commit;
|
||||||
void *buffer;
|
struct tree *tree;
|
||||||
unsigned long size;
|
|
||||||
|
|
||||||
setup_git_directory();
|
setup_git_directory();
|
||||||
|
|
||||||
@ -419,14 +390,13 @@ int main(int argc, char **argv)
|
|||||||
usage(tar_tree_usage);
|
usage(tar_tree_usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = read_object_with_reference(sha1, "commit", &size, commit_sha1);
|
commit = lookup_commit_reference(sha1);
|
||||||
if (buffer) {
|
if (commit) {
|
||||||
write_global_extended_header(commit_sha1);
|
write_global_extended_header(commit->object.sha1);
|
||||||
archive_time = commit_time(buffer, size);
|
archive_time = commit->date;
|
||||||
free(buffer);
|
|
||||||
}
|
}
|
||||||
buffer = read_object_with_reference(sha1, "tree", &size, NULL);
|
tree = parse_tree_indirect(sha1);
|
||||||
if (!buffer)
|
if (!tree)
|
||||||
die("not a reference to a tag, commit or tree object: %s",
|
die("not a reference to a tag, commit or tree object: %s",
|
||||||
sha1_to_hex(sha1));
|
sha1_to_hex(sha1));
|
||||||
if (!archive_time)
|
if (!archive_time)
|
||||||
@ -434,8 +404,7 @@ int main(int argc, char **argv)
|
|||||||
if (basedir)
|
if (basedir)
|
||||||
write_header((unsigned char *)"0", TYPEFLAG_DIR, NULL, NULL,
|
write_header((unsigned char *)"0", TYPEFLAG_DIR, NULL, NULL,
|
||||||
basedir, 040777, NULL, 0);
|
basedir, 040777, NULL, 0);
|
||||||
traverse_tree(buffer, size, NULL);
|
traverse_tree(tree, NULL);
|
||||||
free(buffer);
|
|
||||||
write_trailer();
|
write_trailer();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user