-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move pack_refs() and friends into libgit
This moves pack_refs() and underlying functionality into the library, to make pack-refs functionality easily available to all git programs. Most of builtin-pack-refs.c has been moved verbatim into a new file pack-refs.c that is compiled into libgit.a. A corresponding header file, pack-refs.h, has also been added, declaring pack_refs() and the #defines associated with the flags parameter to pack_refs(). This patch introduces no other changes in functionality. Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Showing
4 changed files
with
138 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#include "cache.h" | ||
#include "refs.h" | ||
#include "tag.h" | ||
#include "pack-refs.h" | ||
|
||
struct ref_to_prune { | ||
struct ref_to_prune *next; | ||
unsigned char sha1[20]; | ||
char name[FLEX_ARRAY]; | ||
}; | ||
|
||
struct pack_refs_cb_data { | ||
unsigned int flags; | ||
struct ref_to_prune *ref_to_prune; | ||
FILE *refs_file; | ||
}; | ||
|
||
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)); | ||
} | ||
|
||
static int handle_one_ref(const char *path, const unsigned char *sha1, | ||
int flags, void *cb_data) | ||
{ | ||
struct pack_refs_cb_data *cb = cb_data; | ||
int is_tag_ref; | ||
|
||
/* Do not pack the symbolic refs */ | ||
if ((flags & REF_ISSYMREF)) | ||
return 0; | ||
is_tag_ref = !prefixcmp(path, "refs/tags/"); | ||
|
||
/* ALWAYS pack refs that were already packed or are tags */ | ||
if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED)) | ||
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) | ||
fprintf(cb->refs_file, "^%s\n", | ||
sha1_to_hex(o->sha1)); | ||
} | ||
} | ||
|
||
if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) { | ||
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; | ||
} | ||
return 0; | ||
} | ||
|
||
/* make sure nobody touched the ref, and unlink */ | ||
static void prune_ref(struct ref_to_prune *r) | ||
{ | ||
struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1); | ||
|
||
if (lock) { | ||
unlink(git_path("%s", r->name)); | ||
unlock_ref(lock); | ||
} | ||
} | ||
|
||
static void prune_refs(struct ref_to_prune *r) | ||
{ | ||
while (r) { | ||
prune_ref(r); | ||
r = r->next; | ||
} | ||
} | ||
|
||
static struct lock_file packed; | ||
|
||
int pack_refs(unsigned int flags) | ||
{ | ||
int fd; | ||
struct pack_refs_cb_data cbdata; | ||
|
||
memset(&cbdata, 0, sizeof(cbdata)); | ||
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); | ||
if (ferror(cbdata.refs_file)) | ||
die("failed to write ref-pack file"); | ||
if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file)) | ||
die("failed to write ref-pack file (%s)", strerror(errno)); | ||
/* | ||
* Since the lock file was fdopen()'ed and then fclose()'ed above, | ||
* assign -1 to the lock file descriptor so that commit_lock_file() | ||
* won't try to close() it. | ||
*/ | ||
packed.fd = -1; | ||
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#ifndef PACK_REFS_H | ||
#define PACK_REFS_H | ||
|
||
/* | ||
* Flags for controlling behaviour of pack_refs() | ||
* PACK_REFS_PRUNE: Prune loose refs after packing | ||
* PACK_REFS_ALL: Pack _all_ refs, not just tags and already packed refs | ||
*/ | ||
#define PACK_REFS_PRUNE 0x0001 | ||
#define PACK_REFS_ALL 0x0002 | ||
|
||
/* | ||
* Write a packed-refs file for the current repository. | ||
* flags: Combination of the above PACK_REFS_* flags. | ||
*/ | ||
int pack_refs(unsigned int flags); | ||
|
||
#endif /* PACK_REFS_H */ |