2007-07-14 23:14:45 +00:00
|
|
|
#include "builtin.h"
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
#include "cache.h"
|
|
|
|
#include "refs.h"
|
2006-11-19 21:22:44 +00:00
|
|
|
#include "object.h"
|
|
|
|
#include "tag.h"
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
|
2006-09-21 07:06:06 +00:00
|
|
|
static const char builtin_pack_refs_usage[] =
|
2007-01-08 22:40:33 +00:00
|
|
|
"git-pack-refs [--all] [--prune | --no-prune]";
|
2006-09-21 07:06:06 +00:00
|
|
|
|
|
|
|
struct ref_to_prune {
|
|
|
|
struct ref_to_prune *next;
|
|
|
|
unsigned char sha1[20];
|
|
|
|
char name[FLEX_ARRAY];
|
|
|
|
};
|
|
|
|
|
2007-05-26 16:25:31 +00:00
|
|
|
#define PACK_REFS_PRUNE 0x0001
|
|
|
|
#define PACK_REFS_ALL 0x0002
|
|
|
|
|
2006-09-21 07:06:06 +00:00
|
|
|
struct pack_refs_cb_data {
|
2007-05-26 16:25:31 +00:00
|
|
|
unsigned int flags;
|
2006-09-21 07:06:06 +00:00
|
|
|
struct ref_to_prune *ref_to_prune;
|
|
|
|
FILE *refs_file;
|
|
|
|
};
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
|
2006-09-21 07:06:06 +00:00
|
|
|
static int do_not_prune(int flags)
|
|
|
|
{
|
|
|
|
/* If it is already packed or if it is a symref,
|
|
|
|
* do not prune it.
|
|
|
|
*/
|
|
|
|
return (flags & (REF_ISSYMREF|REF_ISPACKED));
|
|
|
|
}
|
|
|
|
|
2006-09-21 05:02:01 +00:00
|
|
|
static int handle_one_ref(const char *path, const unsigned char *sha1,
|
|
|
|
int flags, void *cb_data)
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
{
|
2006-09-21 07:06:06 +00:00
|
|
|
struct pack_refs_cb_data *cb = cb_data;
|
2006-11-19 21:22:44 +00:00
|
|
|
int is_tag_ref;
|
2006-09-21 04:47:42 +00:00
|
|
|
|
2006-09-21 07:06:05 +00:00
|
|
|
/* Do not pack the symbolic refs */
|
2006-11-19 21:22:44 +00:00
|
|
|
if ((flags & REF_ISSYMREF))
|
|
|
|
return 0;
|
Mechanical conversion to use prefixcmp()
This mechanically converts strncmp() to use prefixcmp(), but only when
the parameters match specific patterns, so that they can be verified
easily. Leftover from this will be fixed in a separate step, including
idiotic conversions like
if (!strncmp("foo", arg, 3))
=>
if (!(-prefixcmp(arg, "foo")))
This was done by using this script in px.perl
#!/usr/bin/perl -i.bak -p
if (/strncmp\(([^,]+), "([^\\"]*)", (\d+)\)/ && (length($2) == $3)) {
s|strncmp\(([^,]+), "([^\\"]*)", (\d+)\)|prefixcmp($1, "$2")|;
}
if (/strncmp\("([^\\"]*)", ([^,]+), (\d+)\)/ && (length($1) == $3)) {
s|strncmp\("([^\\"]*)", ([^,]+), (\d+)\)|(-prefixcmp($2, "$1"))|;
}
and running:
$ git grep -l strncmp -- '*.c' | xargs perl px.perl
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-20 09:53:29 +00:00
|
|
|
is_tag_ref = !prefixcmp(path, "refs/tags/");
|
2007-01-26 00:51:21 +00:00
|
|
|
|
|
|
|
/* ALWAYS pack refs that were already packed or are tags */
|
2007-05-26 16:25:31 +00:00
|
|
|
if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))
|
2006-11-19 21:22:44 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
|
|
|
|
if (is_tag_ref) {
|
|
|
|
struct object *o = parse_object(sha1);
|
|
|
|
if (o->type == OBJ_TAG) {
|
|
|
|
o = deref_tag(o, path, 0);
|
|
|
|
if (o)
|
2006-11-22 07:36:35 +00:00
|
|
|
fprintf(cb->refs_file, "^%s\n",
|
|
|
|
sha1_to_hex(o->sha1));
|
2006-11-19 21:22:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-26 16:25:31 +00:00
|
|
|
if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {
|
2006-09-21 07:06:06 +00:00
|
|
|
int namelen = strlen(path) + 1;
|
|
|
|
struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
|
|
|
|
hashcpy(n->sha1, sha1);
|
|
|
|
strcpy(n->name, path);
|
|
|
|
n->next = cb->ref_to_prune;
|
|
|
|
cb->ref_to_prune = n;
|
|
|
|
}
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-09-21 07:06:06 +00:00
|
|
|
/* make sure nobody touched the ref, and unlink */
|
|
|
|
static void prune_ref(struct ref_to_prune *r)
|
|
|
|
{
|
2006-09-27 08:09:18 +00:00
|
|
|
struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
|
2006-09-21 07:06:06 +00:00
|
|
|
|
|
|
|
if (lock) {
|
2006-09-23 04:31:40 +00:00
|
|
|
unlink(git_path("%s", r->name));
|
2006-09-21 07:06:06 +00:00
|
|
|
unlock_ref(lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void prune_refs(struct ref_to_prune *r)
|
|
|
|
{
|
|
|
|
while (r) {
|
|
|
|
prune_ref(r);
|
|
|
|
r = r->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-03 09:15:18 +00:00
|
|
|
static struct lock_file packed;
|
|
|
|
|
2007-05-26 16:25:31 +00:00
|
|
|
static int pack_refs(unsigned int flags)
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
{
|
2007-05-26 16:25:31 +00:00
|
|
|
int fd;
|
2006-09-21 07:06:06 +00:00
|
|
|
struct pack_refs_cb_data cbdata;
|
|
|
|
|
|
|
|
memset(&cbdata, 0, sizeof(cbdata));
|
2007-05-26 16:25:31 +00:00
|
|
|
cbdata.flags = flags;
|
|
|
|
|
|
|
|
fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
|
|
|
|
cbdata.refs_file = fdopen(fd, "w");
|
|
|
|
if (!cbdata.refs_file)
|
|
|
|
die("unable to create ref-pack file structure (%s)",
|
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
/* perhaps other traits later as well */
|
|
|
|
fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
|
|
|
|
|
|
|
|
for_each_ref(handle_one_ref, &cbdata);
|
2007-06-24 19:13:11 +00:00
|
|
|
if (ferror(cbdata.refs_file))
|
|
|
|
die("failed to write ref-pack file");
|
2007-05-26 16:25:31 +00:00
|
|
|
if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
|
|
|
|
die("failed to write ref-pack file (%s)", strerror(errno));
|
|
|
|
if (commit_lock_file(&packed) < 0)
|
|
|
|
die("unable to overwrite old ref-pack file (%s)", strerror(errno));
|
|
|
|
if (cbdata.flags & PACK_REFS_PRUNE)
|
|
|
|
prune_refs(cbdata.ref_to_prune);
|
|
|
|
return 0;
|
|
|
|
}
|
2006-09-21 07:06:06 +00:00
|
|
|
|
2007-05-26 16:25:31 +00:00
|
|
|
int cmd_pack_refs(int argc, const char **argv, const char *prefix)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
unsigned int flags;
|
|
|
|
|
|
|
|
flags = PACK_REFS_PRUNE;
|
2006-09-21 07:06:06 +00:00
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
const char *arg = argv[i];
|
|
|
|
if (!strcmp(arg, "--prune")) {
|
2007-05-26 16:25:31 +00:00
|
|
|
flags |= PACK_REFS_PRUNE; /* now the default */
|
2007-01-08 22:40:33 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!strcmp(arg, "--no-prune")) {
|
2007-05-26 16:25:31 +00:00
|
|
|
flags &= ~PACK_REFS_PRUNE;
|
2006-09-21 07:06:06 +00:00
|
|
|
continue;
|
|
|
|
}
|
2006-10-08 08:36:08 +00:00
|
|
|
if (!strcmp(arg, "--all")) {
|
2007-05-26 16:25:31 +00:00
|
|
|
flags |= PACK_REFS_ALL;
|
2006-10-08 08:36:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
2006-09-21 07:06:06 +00:00
|
|
|
/* perhaps other parameters later... */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i != argc)
|
|
|
|
usage(builtin_pack_refs_usage);
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
|
2007-05-26 16:25:31 +00:00
|
|
|
return pack_refs(flags);
|
Start handling references internally as a sorted in-memory list
This also adds some very rudimentary support for the notion of packed
refs. HOWEVER! At this point it isn't used to actually look up a ref
yet, only for listing them (ie "for_each_ref()" and friends see the
packed refs, but none of the other single-ref lookup routines).
Note how we keep two separate lists: one for the loose refs, and one for
the packed refs we read. That's so that we can easily keep the two apart,
and read only one set or the other (and still always make sure that the
loose refs take precedence).
[ From this, it's not actually obvious why we'd keep the two separate
lists, but it's important to have the packed refs on their own list
later on, when I add support for looking up a single loose one.
For that case, we will want to read _just_ the packed refs in case the
single-ref lookup fails, yet we may end up needing the other list at
some point in the future, so keeping them separated is important ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-11 23:37:32 +00:00
|
|
|
}
|