summaryrefslogtreecommitdiff
path: root/builtin-pack-refs.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-09-21 07:40:28 (GMT)
committerJunio C Hamano <junkio@cox.net>2006-09-21 07:40:28 (GMT)
commiteaf12a8c7d844be947c29954b658c17996abcd25 (patch)
tree11bac4c4b10036374b5cc6736fcdf7eee2054c58 /builtin-pack-refs.c
parent9c13359aaf3176428603cc9dfbdf30da889ab3d3 (diff)
parent968846015229fe0fec28e3c85db722e131c15f93 (diff)
downloadgit-eaf12a8c7d844be947c29954b658c17996abcd25.zip
git-eaf12a8c7d844be947c29954b658c17996abcd25.tar.gz
git-eaf12a8c7d844be947c29954b658c17996abcd25.tar.bz2
Merge branch 'lt/refs' into jc/lt-ref2-with-lt-refs
* lt/refs: (58 commits) git-pack-refs --prune pack-refs: do not pack symbolic refs. Tell between packed, unpacked and symbolic refs. Add callback data to for_each_ref() family. symbolit-ref: fix resolve_ref conversion. Fix broken sha1 locking fsck-objects: adjust to resolve_ref() clean-up. gitignore: git-pack-refs is a generated file. wt-status: use simplified resolve_ref to find current branch Fix t1400-update-ref test minimally Enable the packed refs file format Make ref resolution saner Add support for negative refs Start handling references internally as a sorted in-memory list gitweb fix validating pg (page) parameter git-repack(1): document --window and --depth git-apply(1): document --unidiff-zero gitweb: fix warnings in PATH_INFO code and add export_ok/strict_export upload-archive: monitor child communication even more carefully. gitweb: export options ...
Diffstat (limited to 'builtin-pack-refs.c')
-rw-r--r--builtin-pack-refs.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
new file mode 100644
index 0000000..246dd63
--- /dev/null
+++ b/builtin-pack-refs.c
@@ -0,0 +1,112 @@
+#include "cache.h"
+#include "refs.h"
+
+static const char *result_path, *lock_path;
+static const char builtin_pack_refs_usage[] =
+"git-pack-refs [--prune]";
+
+struct ref_to_prune {
+ struct ref_to_prune *next;
+ unsigned char sha1[20];
+ char name[FLEX_ARRAY];
+};
+
+struct pack_refs_cb_data {
+ int prune;
+ struct ref_to_prune *ref_to_prune;
+ FILE *refs_file;
+};
+
+static void remove_lock_file(void)
+{
+ if (lock_path)
+ unlink(lock_path);
+}
+
+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;
+
+ /* Do not pack the symbolic refs */
+ if (!(flags & REF_ISSYMREF))
+ fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
+ if (cb->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, 1);
+
+ if (lock) {
+ unlink(git_path(r->name));
+ unlock_ref(lock);
+ }
+}
+
+static void prune_refs(struct ref_to_prune *r)
+{
+ while (r) {
+ prune_ref(r);
+ r = r->next;
+ }
+}
+
+int cmd_pack_refs(int argc, const char **argv, const char *prefix)
+{
+ int fd, i;
+ struct pack_refs_cb_data cbdata;
+
+ memset(&cbdata, 0, sizeof(cbdata));
+
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (!strcmp(arg, "--prune")) {
+ cbdata.prune = 1;
+ continue;
+ }
+ /* perhaps other parameters later... */
+ break;
+ }
+ if (i != argc)
+ usage(builtin_pack_refs_usage);
+
+ result_path = xstrdup(git_path("packed-refs"));
+ lock_path = xstrdup(mkpath("%s.lock", result_path));
+
+ fd = open(lock_path, O_CREAT | O_EXCL | O_WRONLY, 0666);
+ if (fd < 0)
+ die("unable to create new ref-pack file (%s)", strerror(errno));
+ atexit(remove_lock_file);
+
+ cbdata.refs_file = fdopen(fd, "w");
+ if (!cbdata.refs_file)
+ die("unable to create ref-pack file structure (%s)",
+ strerror(errno));
+ for_each_ref(handle_one_ref, &cbdata);
+ fsync(fd);
+ fclose(cbdata.refs_file);
+ if (rename(lock_path, result_path) < 0)
+ die("unable to overwrite old ref-pack file (%s)", strerror(errno));
+ lock_path = NULL;
+ if (cbdata.prune)
+ prune_refs(cbdata.ref_to_prune);
+ return 0;
+}