Browse Source

Enable the packed refs file format

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>
Signed-off-by: Junio C Hamano <junkio@cox.net>
maint
Linus Torvalds 18 years ago committed by Junio C Hamano
parent
commit
434cd0cd30
  1. 4
      git-checkout.sh
  2. 41
      refs.c
  3. 2
      refs.h

4
git-checkout.sh

@ -22,7 +22,7 @@ while [ "$#" != "0" ]; do
shift shift
[ -z "$newbranch" ] && [ -z "$newbranch" ] &&
die "git checkout: -b needs a branch name" 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" die "git checkout: branch $newbranch already exists"
git-check-ref-format "heads/$newbranch" || git-check-ref-format "heads/$newbranch" ||
die "git checkout: we do not like '$newbranch' as a branch name." die "git checkout: we do not like '$newbranch' as a branch name."
@ -51,7 +51,7 @@ while [ "$#" != "0" ]; do
fi fi
new="$rev" new="$rev"
new_name="$arg^0" new_name="$arg^0"
if [ -f "$GIT_DIR/refs/heads/$arg" ]; then if git-rev-parse "heads/$arg^0" >&/dev/null; then
branch="$arg" branch="$arg"
fi fi
elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null) elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null)

41
refs.c

@ -28,6 +28,8 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
if (!isspace(line[40])) if (!isspace(line[40]))
return NULL; return NULL;
line += 41; line += 41;
if (isspace(*line))
return NULL;
if (line[len] != '\n') if (line[len] != '\n')
return NULL; return NULL;
line[len] = 0; line[len] = 0;
@ -168,6 +170,14 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading)
* reading. * reading.
*/ */
if (lstat(path, &st) < 0) { 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) if (reading || errno != ENOENT)
return NULL; return NULL;
hashclr(sha1); hashclr(sha1);
@ -400,22 +410,13 @@ int check_ref_format(const char *ref)
static struct ref_lock *verify_lock(struct ref_lock *lock, static struct ref_lock *verify_lock(struct ref_lock *lock,
const unsigned char *old_sha1, int mustexist) const unsigned char *old_sha1, int mustexist)
{ {
char buf[40]; if (!resolve_ref(lock->ref_name, lock->old_sha1, mustexist)) {
int nr, fd = open(lock->ref_file, O_RDONLY); error("Can't verify ref %s", lock->ref_name);
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);
unlock_ref(lock); unlock_ref(lock);
return NULL; return NULL;
} }
if (hashcmp(lock->old_sha1, old_sha1)) { 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)); sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1));
unlock_ref(lock); unlock_ref(lock);
return NULL; return NULL;
@ -427,6 +428,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref,
int plen, int plen,
const unsigned char *old_sha1, int mustexist) const unsigned char *old_sha1, int mustexist)
{ {
char *ref_file;
const char *orig_ref = ref; const char *orig_ref = ref;
struct ref_lock *lock; struct ref_lock *lock;
struct stat st; struct stat st;
@ -445,13 +447,14 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref,
} }
lock->lk = xcalloc(1, sizeof(struct lock_file)); 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->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)) if (safe_create_leading_directories(ref_file))
die("unable to create directory for %s", lock->ref_file); die("unable to create directory for %s", ref_file);
lock->lock_fd = hold_lock_file_for_update(lock->lk, lock->ref_file, 1); lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);


return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock; return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
} }
@ -479,7 +482,7 @@ void unlock_ref(struct ref_lock *lock)
if (lock->lk) if (lock->lk)
rollback_lock_file(lock->lk); rollback_lock_file(lock->lk);
} }
free(lock->ref_file); free(lock->ref_name);
free(lock->log_file); free(lock->log_file);
free(lock); free(lock);
} }
@ -556,7 +559,7 @@ int write_ref_sha1(struct ref_lock *lock,
return -1; return -1;
} }
if (commit_lock_file(lock->lk)) { 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); unlock_ref(lock);
return -1; return -1;
} }

2
refs.h

@ -2,7 +2,7 @@
#define REFS_H #define REFS_H


struct ref_lock { struct ref_lock {
char *ref_file; char *ref_name;
char *log_file; char *log_file;
struct lock_file *lk; struct lock_file *lk;
unsigned char old_sha1[20]; unsigned char old_sha1[20];

Loading…
Cancel
Save