git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Enable the packed refs file format
@ 2006-09-14 17:14 Linus Torvalds
  2006-09-19 20:55 ` Petr Baudis
  0 siblings, 1 reply; 8+ messages in thread
From: Linus Torvalds @ 2006-09-14 17:14 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List


This actually "turns on" the packed ref file format, now that the 
infrastructure to do so sanely exists (ie notably the change to make the 
reference reading logic take refnames rather than pathnames to the loose 
objects that no longer necessarily even exist).

In particular, when the ref lookup hits a refname that has no loose file 
associated with it, it falls back on the packed-ref information. Also, the 
ref-locking code, while still using a loose file for the locking itself 
(and _creating_ a loose file for the new ref) no longer requires that the 
old ref be in such an unpacked state.

Finally, this does a minimal hack to git-checkout.sh to rather than check 
the ref-file directly, do a "git-rev-parse" on the "heads/$refname". 
That's not really wonderful - we should rather really have a special 
routine to verify the names as proper branch head names, but it is a 
workable solution for now.

With this, I can literally do something like

	git pack-refs
	find .git/refs -type f -print0 | xargs -0 rm -f --

and the end result is a largely working repository (ie I've done two 
commits - which creates _one_ unpacked ref file - done things like run 
"gitk" and "git log" etc, and it all looks ok).

There are probably things missing, but I'm hoping that the missing things 
are now of the "small and obvious" kind, and that somebody else might want 
to start looking at this too. Hint hint ;)

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---

This obviously depends on the lt/refs branch in Junio's tree, that is 
currently only in -pu.

diff --git a/git-checkout.sh b/git-checkout.sh
index 580a9e8..c60e029 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -22,7 +22,7 @@ while [ "$#" != "0" ]; do
 		shift
 		[ -z "$newbranch" ] &&
 			die "git checkout: -b needs a branch name"
-		[ -e "$GIT_DIR/refs/heads/$newbranch" ] &&
+		git-rev-parse --symbolic "heads/$newbranch" >&/dev/null &&
 			die "git checkout: branch $newbranch already exists"
 		git-check-ref-format "heads/$newbranch" ||
 			die "git checkout: we do not like '$newbranch' as a branch name."
@@ -51,7 +51,7 @@ while [ "$#" != "0" ]; do
 			fi
 			new="$rev"
 			new_name="$arg^0"
-			if [ -f "$GIT_DIR/refs/heads/$arg" ]; then
+			if git-rev-parse "heads/$arg^0" >&/dev/null; then
 				branch="$arg"
 			fi
 		elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null)
diff --git a/refs.c b/refs.c
index 50c25d3..134c0fc 100644
--- a/refs.c
+++ b/refs.c
@@ -28,6 +28,8 @@ static const char *parse_ref_line(char *
 	if (!isspace(line[40]))
 		return NULL;
 	line += 41;
+	if (isspace(*line))
+		return NULL;
 	if (line[len] != '\n')
 		return NULL;
 	line[len] = 0;
@@ -168,6 +170,14 @@ const char *resolve_ref(const char *ref,
 		 * reading.
 		 */
 		if (lstat(path, &st) < 0) {
+			struct ref_list *list = get_packed_refs();
+			while (list) {
+				if (!strcmp(ref, list->name)) {
+					hashcpy(sha1, list->sha1);
+					return ref;
+				}
+				list = list->next;
+			}
 			if (reading || errno != ENOENT)
 				return NULL;
 			hashclr(sha1);
@@ -400,22 +410,13 @@ int check_ref_format(const char *ref)
 static struct ref_lock *verify_lock(struct ref_lock *lock,
 	const unsigned char *old_sha1, int mustexist)
 {
-	char buf[40];
-	int nr, fd = open(lock->ref_file, O_RDONLY);
-	if (fd < 0 && (mustexist || errno != ENOENT)) {
-		error("Can't verify ref %s", lock->ref_file);
-		unlock_ref(lock);
-		return NULL;
-	}
-	nr = read(fd, buf, 40);
-	close(fd);
-	if (nr != 40 || get_sha1_hex(buf, lock->old_sha1) < 0) {
-		error("Can't verify ref %s", lock->ref_file);
+	if (!resolve_ref(lock->ref_name, lock->old_sha1, mustexist)) {
+		error("Can't verify ref %s", lock->ref_name);
 		unlock_ref(lock);
 		return NULL;
 	}
 	if (hashcmp(lock->old_sha1, old_sha1)) {
-		error("Ref %s is at %s but expected %s", lock->ref_file,
+		error("Ref %s is at %s but expected %s", lock->ref_name,
 			sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1));
 		unlock_ref(lock);
 		return NULL;
@@ -427,6 +428,7 @@ static struct ref_lock *lock_ref_sha1_ba
 	int plen,
 	const unsigned char *old_sha1, int mustexist)
 {
+	char *ref_file;
 	const char *orig_ref = ref;
 	struct ref_lock *lock;
 	struct stat st;
@@ -445,13 +447,14 @@ static struct ref_lock *lock_ref_sha1_ba
 	}
 	lock->lk = xcalloc(1, sizeof(struct lock_file));
 
-	lock->ref_file = xstrdup(git_path("%s", ref));
+	lock->ref_name = xstrdup(ref);
 	lock->log_file = xstrdup(git_path("logs/%s", ref));
-	lock->force_write = lstat(lock->ref_file, &st) && errno == ENOENT;
+	ref_file = git_path(ref);
+	lock->force_write = lstat(ref_file, &st) && errno == ENOENT;
 
-	if (safe_create_leading_directories(lock->ref_file))
-		die("unable to create directory for %s", lock->ref_file);
-	lock->lock_fd = hold_lock_file_for_update(lock->lk, lock->ref_file, 1);
+	if (safe_create_leading_directories(ref_file))
+		die("unable to create directory for %s", ref_file);
+	lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
 
 	return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
 }
@@ -479,7 +482,7 @@ void unlock_ref(struct ref_lock *lock)
 		if (lock->lk)
 			rollback_lock_file(lock->lk);
 	}
-	free(lock->ref_file);
+	free(lock->ref_name);
 	free(lock->log_file);
 	free(lock);
 }
@@ -556,7 +559,7 @@ int write_ref_sha1(struct ref_lock *lock
 		return -1;
 	}
 	if (commit_lock_file(lock->lk)) {
-		error("Couldn't set %s", lock->ref_file);
+		error("Couldn't set %s", lock->ref_name);
 		unlock_ref(lock);
 		return -1;
 	}
diff --git a/refs.h b/refs.h
index 553155c..af347e6 100644
--- a/refs.h
+++ b/refs.h
@@ -2,7 +2,7 @@ #ifndef REFS_H
 #define REFS_H
 
 struct ref_lock {
-	char *ref_file;
+	char *ref_name;
 	char *log_file;
 	struct lock_file *lk;
 	unsigned char old_sha1[20];

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2006-09-23  4:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-14 17:14 Enable the packed refs file format Linus Torvalds
2006-09-19 20:55 ` Petr Baudis
2006-09-19 21:09   ` Linus Torvalds
2006-09-20 20:19     ` Phil Richards
2006-09-22 23:08   ` [PATCH] Fix buggy ref recording Petr Baudis
2006-09-23  0:44     ` Junio C Hamano
2006-09-23  1:16       ` Petr Baudis
2006-09-23  4:34         ` [PATCH] pack-refs: fix git_path() usage Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).