Merge branch 'lt/refs' into next

* lt/refs:
  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.
This commit is contained in:
Junio C Hamano
2006-09-17 19:24:00 -07:00
18 changed files with 360 additions and 173 deletions

View File

@@ -95,6 +95,16 @@ OPTIONS
context exist they all must match. By default no context is
ever ignored.
--unidiff-zero::
By default, gitlink:git-apply[1] expects that the patch being
applied is a unified diff with at least one line of context.
This provides good safety measures, but breaks down when
applying a diff generated with --unified=0. To bypass these
checks use '--unidiff-zero'.
+
Note, for the reasons stated above usage of context-free patches are
discouraged.
--apply::
If you use any of the options marked "Turns off
'apply'" above, gitlink:git-apply[1] reads and outputs the

View File

@@ -9,7 +9,7 @@ objects into pack files.
SYNOPSIS
--------
'git-repack' [-a] [-d] [-f] [-l] [-n] [-q]
'git-repack' [-a] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
DESCRIPTION
-----------
@@ -56,6 +56,16 @@ OPTIONS
Do not update the server information with
`git update-server-info`.
--window=[N], --depth=[N]::
These two options affects how the objects contained in the pack are
stored using delta compression. The objects are first internally
sorted by type, size and optionally names and compared against the
other objects within `--window` to see if using delta compression saves
space. `--depth` limits the maximum delta depth; making it too deep
affects the performance on the unpacker side, because delta data needs
to be applied that many times to get to the necessary object.
Author
------
Written by Linus Torvalds <torvalds@osdl.org>

View File

@@ -314,7 +314,8 @@ BUILTIN_OBJS = \
builtin-verify-pack.o \
builtin-write-tree.o \
builtin-zip-tree.o \
builtin-show-ref.o
builtin-show-ref.o \
builtin-pack-refs.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
EXTLIBS = -lz

View File

@@ -249,7 +249,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
FILE *in = stdin;
const char *sep = "";
unsigned char head_sha1[20];
const char *head, *current_branch;
const char *current_branch;
git_config(fmt_merge_msg_config);
@@ -277,10 +277,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
usage(fmt_merge_msg_usage);
/* get current branch */
head = xstrdup(git_path("HEAD"));
current_branch = resolve_ref(head, head_sha1, 1);
current_branch += strlen(head) - 4;
free((char *)head);
current_branch = resolve_ref("HEAD", head_sha1, 1);
if (!strncmp(current_branch, "refs/heads/", 11))
current_branch += 11;

View File

@@ -218,8 +218,8 @@ static void create_default_files(const char *git_dir, const char *template_path)
* branch, if it does not exist yet.
*/
strcpy(path + len, "HEAD");
if (read_ref(path, sha1) < 0) {
if (create_symref(path, "refs/heads/master") < 0)
if (read_ref("HEAD", sha1) < 0) {
if (create_symref("HEAD", "refs/heads/master") < 0)
exit(1);
}

41
builtin-pack-refs.c Normal file
View File

@@ -0,0 +1,41 @@
#include "cache.h"
#include "refs.h"
static FILE *refs_file;
static const char *result_path, *lock_path;
static void remove_lock_file(void)
{
if (lock_path)
unlink(lock_path);
}
static int handle_one_ref(const char *path, const unsigned char *sha1)
{
fprintf(refs_file, "%s %s\n", sha1_to_hex(sha1), path);
return 0;
}
int cmd_pack_refs(int argc, const char **argv, const char *prefix)
{
int fd;
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);
refs_file = fdopen(fd, "w");
if (!refs_file)
die("unable to create ref-pack file structure (%s)", strerror(errno));
for_each_ref(handle_one_ref);
fsync(fd);
fclose(refs_file);
if (rename(lock_path, result_path) < 0)
die("unable to overwrite old ref-pack file (%s)", strerror(errno));
lock_path = NULL;
return 0;
}

View File

@@ -437,21 +437,13 @@ static void snarf_refs(int head, int tag)
}
}
static int rev_is_head(char *head_path, int headlen, char *name,
static int rev_is_head(char *head, int headlen, char *name,
unsigned char *head_sha1, unsigned char *sha1)
{
int namelen;
if ((!head_path[0]) ||
if ((!head[0]) ||
(head_sha1 && sha1 && hashcmp(head_sha1, sha1)))
return 0;
namelen = strlen(name);
if ((headlen < namelen) ||
memcmp(head_path + headlen - namelen, name, namelen))
return 0;
if (headlen == namelen ||
head_path[headlen - namelen - 1] == '/')
return 1;
return 0;
return !strcmp(head, name);
}
static int show_merge_base(struct commit_list *seen, int num_rev)
@@ -559,9 +551,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
int all_heads = 0, all_tags = 0;
int all_mask, all_revs;
int lifo = 1;
char head_path[128];
const char *head_path_p;
int head_path_len;
char head[128];
const char *head_p;
int head_len;
unsigned char head_sha1[20];
int merge_base = 0;
int independent = 0;
@@ -638,31 +630,31 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
ac--; av++;
}
head_path_p = resolve_ref(git_path("HEAD"), head_sha1, 1);
if (head_path_p) {
head_path_len = strlen(head_path_p);
memcpy(head_path, head_path_p, head_path_len + 1);
head_p = resolve_ref("HEAD", head_sha1, 1);
if (head_p) {
head_len = strlen(head_p);
memcpy(head, head_p, head_len + 1);
}
else {
head_path_len = 0;
head_path[0] = 0;
head_len = 0;
head[0] = 0;
}
if (with_current_branch && head_path_p) {
if (with_current_branch && head_p) {
int has_head = 0;
for (i = 0; !has_head && i < ref_name_cnt; i++) {
/* We are only interested in adding the branch
* HEAD points at.
*/
if (rev_is_head(head_path,
head_path_len,
if (rev_is_head(head,
head_len,
ref_name[i],
head_sha1, NULL))
has_head++;
}
if (!has_head) {
int pfxlen = strlen(git_path("refs/heads/"));
append_one_rev(head_path + pfxlen);
int pfxlen = strlen("refs/heads/");
append_one_rev(head + pfxlen);
}
}
@@ -713,8 +705,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (1 < num_rev || extra < 0) {
for (i = 0; i < num_rev; i++) {
int j;
int is_head = rev_is_head(head_path,
head_path_len,
int is_head = rev_is_head(head,
head_len,
ref_name[i],
head_sha1,
rev[i]->object.sha1);

View File

@@ -7,15 +7,11 @@ static const char git_symbolic_ref_usage[] =
static void check_symref(const char *HEAD)
{
unsigned char sha1[20];
const char *git_HEAD = xstrdup(git_path("%s", HEAD));
const char *git_refs_heads_master = resolve_ref(git_HEAD, sha1, 0);
if (git_refs_heads_master) {
/* we want to strip the .git/ part */
int pfxlen = strlen(git_HEAD) - strlen(HEAD);
puts(git_refs_heads_master + pfxlen);
}
else
const char *refs_heads_master = resolve_ref("HEAD", sha1, 0);
if (!refs_heads_master)
die("No such ref: %s", HEAD);
puts(refs_heads_master);
}
int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
@@ -26,7 +22,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
check_symref(argv[1]);
break;
case 3:
create_symref(xstrdup(git_path("%s", argv[1])), argv[2]);
create_symref(argv[1], argv[2]);
break;
default:
usage(git_symbolic_ref_usage);

View File

@@ -160,7 +160,8 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
if (pfd[1].revents & POLLIN)
/* Status stream ready */
process_input(pfd[1].fd, 2);
if ((pfd[0].revents | pfd[1].revents) == POLLIN)
/* Always finish to read data when available */
if ((pfd[0].revents | pfd[1].revents) & POLLIN)
continue;
if (waitpid(writer, &status, 0) < 0)

View File

@@ -65,5 +65,6 @@ extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);
extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
extern int cmd_pack_refs(int argc, const char **argv, const char *prefix);
#endif

View File

@@ -287,8 +287,8 @@ extern int get_sha1_hex(const char *hex, unsigned char *sha1);
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
extern int read_ref(const char *filename, unsigned char *sha1);
extern const char *resolve_ref(const char *path, unsigned char *sha1, int);
extern int create_symref(const char *git_HEAD, const char *refs_heads_master);
extern int validate_symref(const char *git_HEAD);
extern int create_symref(const char *ref, const char *refs_heads_master);
extern int validate_symref(const char *ref);
extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2);

1
git.c
View File

@@ -271,6 +271,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "write-tree", cmd_write_tree, RUN_SETUP },
{ "verify-pack", cmd_verify_pack },
{ "show-ref", cmd_show_ref, RUN_SETUP },
{ "pack-refs", cmd_pack_refs, RUN_SETUP },
};
int i;

View File

@@ -189,9 +189,6 @@ do $GITWEB_CONFIG if -e $GITWEB_CONFIG;
# version of the core git binary
our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown";
# path to the current git repository
our $git_dir;
$projects_list ||= $projectroot;
# ======================================================================
@@ -259,7 +256,7 @@ if (defined $hash_parent_base) {
our $page = $cgi->param('pg');
if (defined $page) {
if ($page =~ m/[^0-9]$/) {
if ($page =~ m/[^0-9]/) {
die_error(undef, "Invalid page parameter");
}
}
@@ -273,30 +270,41 @@ if (defined $searchtext) {
}
# now read PATH_INFO and use it as alternative to parameters
our $path_info = $ENV{"PATH_INFO"};
$path_info =~ s|^/||;
$path_info =~ s|/$||;
if (validate_input($path_info) && !defined $project) {
sub evaluate_path_info {
return if defined $project;
my $path_info = $ENV{"PATH_INFO"};
return if !$path_info;
$path_info =~ s,(^/|/$),,gs;
$path_info = validate_input($path_info);
return if !$path_info;
$project = $path_info;
while ($project && !-e "$projectroot/$project/HEAD") {
$project =~ s,/*[^/]*$,,;
}
if (defined $project) {
$project = undef unless $project;
if (!$project ||
($export_ok && !-e "$projectroot/$project/$export_ok") ||
($strict_export && !project_in_list($project))) {
undef $project;
return;
}
# do not change any parameters if an action is given using the query string
return if $action;
if ($path_info =~ m,^$project/([^/]+)/(.+)$,) {
# we got "project.git/branch/filename"
$action ||= "blob_plain";
$hash_base ||= $1;
$file_name ||= $2;
$hash_base ||= validate_input($1);
$file_name ||= validate_input($2);
} elsif ($path_info =~ m,^$project/([^/]+)$,) {
# we got "project.git/branch"
$action ||= "shortlog";
$hash ||= $1;
$hash ||= validate_input($1);
}
}
evaluate_path_info();
$git_dir = "$projectroot/$project";
# path to the current git repository
our $git_dir;
$git_dir = "$projectroot/$project" if $project;
# dispatch
my %actions = (

322
refs.c
View File

@@ -3,15 +3,158 @@
#include <errno.h>
struct ref_list {
struct ref_list *next;
unsigned char sha1[20];
char name[FLEX_ARRAY];
};
static const char *parse_ref_line(char *line, unsigned char *sha1)
{
/*
* 42: the answer to everything.
*
* In this case, it happens to be the answer to
* 40 (length of sha1 hex representation)
* +1 (space in between hex and name)
* +1 (newline at the end of the line)
*/
int len = strlen(line) - 42;
if (len <= 0)
return NULL;
if (get_sha1_hex(line, sha1) < 0)
return NULL;
if (!isspace(line[40]))
return NULL;
line += 41;
if (isspace(*line))
return NULL;
if (line[len] != '\n')
return NULL;
line[len] = 0;
return line;
}
static struct ref_list *add_ref(const char *name, const unsigned char *sha1, struct ref_list *list)
{
int len;
struct ref_list **p = &list, *entry;
/* Find the place to insert the ref into.. */
while ((entry = *p) != NULL) {
int cmp = strcmp(entry->name, name);
if (cmp > 0)
break;
/* Same as existing entry? */
if (!cmp)
return list;
p = &entry->next;
}
/* Allocate it and add it in.. */
len = strlen(name) + 1;
entry = xmalloc(sizeof(struct ref_list) + len);
hashcpy(entry->sha1, sha1);
memcpy(entry->name, name, len);
entry->next = *p;
*p = entry;
return list;
}
static struct ref_list *get_packed_refs(void)
{
static int did_refs = 0;
static struct ref_list *refs = NULL;
if (!did_refs) {
FILE *f = fopen(git_path("packed-refs"), "r");
if (f) {
struct ref_list *list = NULL;
char refline[PATH_MAX];
while (fgets(refline, sizeof(refline), f)) {
unsigned char sha1[20];
const char *name = parse_ref_line(refline, sha1);
if (!name)
continue;
list = add_ref(name, sha1, list);
}
fclose(f);
refs = list;
}
did_refs = 1;
}
return refs;
}
static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
{
DIR *dir = opendir(git_path("%s", base));
if (dir) {
struct dirent *de;
int baselen = strlen(base);
char *ref = xmalloc(baselen + 257);
memcpy(ref, base, baselen);
if (baselen && base[baselen-1] != '/')
ref[baselen++] = '/';
while ((de = readdir(dir)) != NULL) {
unsigned char sha1[20];
struct stat st;
int namelen;
if (de->d_name[0] == '.')
continue;
namelen = strlen(de->d_name);
if (namelen > 255)
continue;
if (has_extension(de->d_name, ".lock"))
continue;
memcpy(ref + baselen, de->d_name, namelen+1);
if (stat(git_path("%s", ref), &st) < 0)
continue;
if (S_ISDIR(st.st_mode)) {
list = get_ref_dir(ref, list);
continue;
}
if (read_ref(ref, sha1) < 0) {
error("%s points nowhere!", ref);
continue;
}
list = add_ref(ref, sha1, list);
}
free(ref);
closedir(dir);
}
return list;
}
static struct ref_list *get_loose_refs(void)
{
static int did_refs = 0;
static struct ref_list *refs = NULL;
if (!did_refs) {
refs = get_ref_dir("refs", NULL);
did_refs = 1;
}
return refs;
}
/* We allow "recursive" symbolic refs. Only within reason, though */
#define MAXDEPTH 5
const char *resolve_ref(const char *path, unsigned char *sha1, int reading)
const char *resolve_ref(const char *ref, unsigned char *sha1, int reading)
{
int depth = MAXDEPTH, len;
char buffer[256];
static char ref_buffer[256];
for (;;) {
const char *path = git_path("%s", ref);
struct stat st;
char *buf;
int fd;
@@ -27,17 +170,27 @@ const char *resolve_ref(const char *path, unsigned char *sha1, int reading)
* 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);
return path;
return ref;
}
/* Follow "normalized" - ie "refs/.." symlinks by hand */
if (S_ISLNK(st.st_mode)) {
len = readlink(path, buffer, sizeof(buffer)-1);
if (len >= 5 && !memcmp("refs/", buffer, 5)) {
path = git_path("%.*s", len, buffer);
buffer[len] = 0;
strcpy(ref_buffer, buffer);
ref = ref_buffer;
continue;
}
}
@@ -62,19 +215,22 @@ const char *resolve_ref(const char *path, unsigned char *sha1, int reading)
while (len && isspace(*buf))
buf++, len--;
while (len && isspace(buf[len-1]))
buf[--len] = 0;
path = git_path("%.*s", len, buf);
len--;
buf[len] = 0;
memcpy(ref_buffer, buf, len + 1);
ref = ref_buffer;
}
if (len < 40 || get_sha1_hex(buffer, sha1))
return NULL;
return path;
return ref;
}
int create_symref(const char *git_HEAD, const char *refs_heads_master)
int create_symref(const char *ref_target, const char *refs_heads_master)
{
const char *lockpath;
char ref[1000];
int fd, len, written;
const char *git_HEAD = git_path("%s", ref_target);
#ifndef NO_SYMLINK_HEAD
if (prefer_symlink_refs) {
@@ -112,104 +268,91 @@ int create_symref(const char *git_HEAD, const char *refs_heads_master)
return 0;
}
int read_ref(const char *filename, unsigned char *sha1)
int read_ref(const char *ref, unsigned char *sha1)
{
if (resolve_ref(filename, sha1, 1))
if (resolve_ref(ref, sha1, 1))
return 0;
return -1;
}
static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1), int trim)
{
int retval = 0;
DIR *dir = opendir(git_path("%s", base));
int retval;
struct ref_list *packed = get_packed_refs();
struct ref_list *loose = get_loose_refs();
if (dir) {
struct dirent *de;
int baselen = strlen(base);
char *path = xmalloc(baselen + 257);
if (!strncmp(base, "./", 2)) {
base += 2;
baselen -= 2;
while (packed && loose) {
struct ref_list *entry;
int cmp = strcmp(packed->name, loose->name);
if (!cmp) {
packed = packed->next;
continue;
}
memcpy(path, base, baselen);
if (baselen && base[baselen-1] != '/')
path[baselen++] = '/';
while ((de = readdir(dir)) != NULL) {
unsigned char sha1[20];
struct stat st;
int namelen;
if (de->d_name[0] == '.')
continue;
namelen = strlen(de->d_name);
if (namelen > 255)
continue;
if (has_extension(de->d_name, ".lock"))
continue;
memcpy(path + baselen, de->d_name, namelen+1);
if (stat(git_path("%s", path), &st) < 0)
continue;
if (S_ISDIR(st.st_mode)) {
retval = do_for_each_ref(path, fn, trim);
if (retval)
break;
continue;
}
if (read_ref(git_path("%s", path), sha1) < 0) {
error("%s points nowhere!", path);
continue;
}
if (!has_sha1_file(sha1)) {
error("%s does not point to a valid "
"commit object!", path);
continue;
}
retval = fn(path + trim, sha1);
if (retval)
break;
if (cmp > 0) {
entry = loose;
loose = loose->next;
} else {
entry = packed;
packed = packed->next;
}
free(path);
closedir(dir);
if (strncmp(base, entry->name, trim))
continue;
if (is_null_sha1(entry->sha1))
continue;
if (!has_sha1_file(entry->sha1)) {
error("%s does not point to a valid object!", entry->name);
continue;
}
retval = fn(entry->name + trim, entry->sha1);
if (retval)
return retval;
}
return retval;
packed = packed ? packed : loose;
while (packed) {
if (!strncmp(base, packed->name, trim)) {
retval = fn(packed->name + trim, packed->sha1);
if (retval)
return retval;
}
packed = packed->next;
}
return 0;
}
int head_ref(int (*fn)(const char *path, const unsigned char *sha1))
{
unsigned char sha1[20];
if (!read_ref(git_path("HEAD"), sha1))
if (!read_ref("HEAD", sha1))
return fn("HEAD", sha1);
return 0;
}
int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1))
{
return do_for_each_ref("refs", fn, 0);
return do_for_each_ref("refs/", fn, 0);
}
int for_each_tag_ref(int (*fn)(const char *path, const unsigned char *sha1))
{
return do_for_each_ref("refs/tags", fn, 10);
return do_for_each_ref("refs/tags/", fn, 10);
}
int for_each_branch_ref(int (*fn)(const char *path, const unsigned char *sha1))
{
return do_for_each_ref("refs/heads", fn, 11);
return do_for_each_ref("refs/heads/", fn, 11);
}
int for_each_remote_ref(int (*fn)(const char *path, const unsigned char *sha1))
{
return do_for_each_ref("refs/remotes", fn, 13);
return do_for_each_ref("refs/remotes/", fn, 13);
}
int get_ref_sha1(const char *ref, unsigned char *sha1)
{
if (check_ref_format(ref))
return -1;
return read_ref(git_path("refs/%s", ref), sha1);
return read_ref(mkpath("refs/%s", ref), sha1);
}
/*
@@ -267,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;
@@ -290,36 +424,37 @@ static struct ref_lock *verify_lock(struct ref_lock *lock,
return lock;
}
static struct ref_lock *lock_ref_sha1_basic(const char *path,
static struct ref_lock *lock_ref_sha1_basic(const char *ref,
int plen,
const unsigned char *old_sha1, int mustexist)
{
const char *orig_path = path;
char *ref_file;
const char *orig_ref = ref;
struct ref_lock *lock;
struct stat st;
lock = xcalloc(1, sizeof(struct ref_lock));
lock->lock_fd = -1;
plen = strlen(path) - plen;
path = resolve_ref(path, lock->old_sha1, mustexist);
if (!path) {
ref = resolve_ref(ref, lock->old_sha1, mustexist);
if (!ref) {
int last_errno = errno;
error("unable to resolve reference %s: %s",
orig_path, strerror(errno));
orig_ref, strerror(errno));
unlock_ref(lock);
errno = last_errno;
return NULL;
}
lock->lk = xcalloc(1, sizeof(struct lock_file));
lock->ref_file = xstrdup(path);
lock->log_file = xstrdup(git_path("logs/%s", lock->ref_file + plen));
lock->force_write = lstat(lock->ref_file, &st) && errno == ENOENT;
lock->ref_name = xstrdup(ref);
lock->log_file = xstrdup(git_path("logs/%s", ref));
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;
}
@@ -329,15 +464,14 @@ struct ref_lock *lock_ref_sha1(const char *ref,
{
if (check_ref_format(ref))
return NULL;
return lock_ref_sha1_basic(git_path("refs/%s", ref),
return lock_ref_sha1_basic(mkpath("refs/%s", ref),
5 + strlen(ref), old_sha1, mustexist);
}
struct ref_lock *lock_any_ref_for_update(const char *ref,
const unsigned char *old_sha1, int mustexist)
{
return lock_ref_sha1_basic(git_path("%s", ref),
strlen(ref), old_sha1, mustexist);
return lock_ref_sha1_basic(ref, strlen(ref), old_sha1, mustexist);
}
void unlock_ref(struct ref_lock *lock)
@@ -348,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);
}
@@ -425,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;
}

2
refs.h
View File

@@ -2,7 +2,7 @@
#define REFS_H
struct ref_lock {
char *ref_file;
char *ref_name;
char *log_file;
struct lock_file *lk;
unsigned char old_sha1[20];

View File

@@ -247,8 +247,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
NULL
};
static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
const char **p, *pathname;
char *real_path = NULL;
const char **p, *ref;
char *real_ref = NULL;
int refs_found = 0, am;
unsigned long at_time = (unsigned long)-1;
unsigned char *this_result;
@@ -276,10 +276,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
for (p = fmt; *p; p++) {
this_result = refs_found ? sha1_from_ref : sha1;
pathname = resolve_ref(git_path(*p, len, str), this_result, 1);
if (pathname) {
ref = resolve_ref(mkpath(*p, len, str), this_result, 1);
if (ref) {
if (!refs_found++)
real_path = xstrdup(pathname);
real_ref = xstrdup(ref);
if (!warn_ambiguous_refs)
break;
}
@@ -293,12 +293,12 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
if (at_time != (unsigned long)-1) {
read_ref_at(
real_path + strlen(git_path(".")) - 1,
real_ref,
at_time,
sha1);
}
free(real_path);
free(real_ref);
return 0;
}

View File

@@ -30,11 +30,8 @@ rm -f .git/$m
test_expect_success \
"fail to create $n" \
"touch .git/$n_dir
git-update-ref $n $A >out 2>err
test "'$? = 1 &&
test "" = "$(cat out)" &&
grep "error: unable to resolve reference" err &&
grep '"$n err"
git-update-ref $n $A >out 2>err"'
test $? != 0'
rm -f .git/$n_dir out err
test_expect_success \

View File

@@ -41,10 +41,8 @@ void wt_status_prepare(struct wt_status *s)
s->is_initial = get_sha1("HEAD", sha1) ? 1 : 0;
head = resolve_ref(git_path("HEAD"), sha1, 0);
s->branch = head ?
strdup(head + strlen(get_git_dir()) + 1) :
NULL;
head = resolve_ref("HEAD", sha1, 0);
s->branch = head ? xstrdup(head) : NULL;
s->reference = "HEAD";
s->amend = 0;