From d711de55280c3c9c10cfda4e24c8f3b3015217b2 Mon Sep 17 00:00:00 2001 From: Julius Plenz Date: Thu, 7 Apr 2011 12:59:24 +0200 Subject: guess default branch from HEAD This is a saner alternative than hardcoding the default branch to be "master". The add_repo() function will now check for a symbolic ref in repo_path/HEAD. If there is a suitable one, overwrite repo->defbranch with it. Note that you'll need to strip the newline from the file (-> len-17). If HEAD is a symbolic link pointing directly to a branch below refs/heads/, do a readlink() instead to find the ref name. Signed-off-by: Julius Plenz Signed-off-by: Lars Hjemli --- cgitrc.5.txt | 3 ++- scan-tree.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 4721c1e..c2c5680 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -377,7 +377,8 @@ repo.commit-filter:: repo.defbranch:: The name of the default branch for this repository. If no such branch exists in the repository, the first branch name (when sorted) is used - as default instead. Default value: "master". + as default instead. Default value: branch pointed to by HEAD, or + "master" if there is no suitable HEAD. repo.desc:: The value to show as repository description. Default value: none. diff --git a/scan-tree.c b/scan-tree.c index 378d795..a429a9f 100644 --- a/scan-tree.c +++ b/scan-tree.c @@ -68,6 +68,39 @@ static char *xstrrchr(char *s, char *from, int c) return from < s ? NULL : from; } +static char *guess_defbranch(const char *repo_path) +{ + int fd, len; + char buffer[256]; + char *ref_start; + char *head; + + head = fmt("%s/HEAD", repo_path); + fd = open(head, O_RDONLY); + if (fd == -1) + return xstrdup("master"); + + memset(buffer, 0, sizeof(buffer)); + len = read_in_full(fd, buffer, sizeof(buffer)-1); + close(fd); + + if(!memcmp(buffer, "ref: refs/heads/", 16)) + return xstrndup(buffer+16, len-17); + + if(strlen(buffer) == 41) { + /* probably contains a SHA1 sum */ + memset(buffer, 0, sizeof(buffer)); + if(readlink(head, buffer, sizeof(buffer)-1)) { + ref_start = memmem(buffer, sizeof(buffer)-1, "refs/heads/", 11); + if(ref_start) + return xstrdup(ref_start+11); + } + } + + return xstrdup("master"); +} + + static void add_repo(const char *base, const char *path, repo_config_fn fn) { struct stat st; @@ -105,6 +138,9 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn) *p = '\0'; repo->name = repo->url; repo->path = xstrdup(path); + + repo->defbranch = guess_defbranch(repo->path); + while (!owner) { if ((pwd = getpwuid(st.st_uid)) == NULL) { fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", -- cgit v1.2.3-70-g09d2 From e95c70d4ea997d1217d5c81cb3b640f3fa025df1 Mon Sep 17 00:00:00 2001 From: Lars Hjemli Date: Mon, 20 Jun 2011 20:59:10 +0200 Subject: Only guess default branch when a repo page is requested There's no need to invoke guess_defbranch() for each repo during scan-path, since repo.defbranch is only used when repo content is being displayed. Also, some users prefer to register their projects manually in cgitrc but they got no benefit from the new repo.defbranch handling. This patch tries to rectify these issues by only invoking guess_defbranch() when needed, regardless of how the repo was registered. Signed-off-by: Lars Hjemli --- cgit.c | 35 ++++++++++++++++++++++++++++++++++- scan-tree.c | 36 ------------------------------------ shared.c | 1 - 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/cgit.c b/cgit.c index b7807ad..e3fbbf4 100644 --- a/cgit.c +++ b/cgit.c @@ -416,6 +416,37 @@ char *find_default_branch(struct cgit_repo *repo) return ref; } +static char *guess_defbranch(const char *repo_path) +{ + int fd, len; + char buffer[256]; + char *ref_start; + char *head; + + head = fmt("%s/HEAD", repo_path); + fd = open(head, O_RDONLY); + if (fd == -1) + return xstrdup("master"); + + memset(buffer, 0, sizeof(buffer)); + len = read_in_full(fd, buffer, sizeof(buffer) - 1); + close(fd); + + if(!memcmp(buffer, "ref: refs/heads/", 16)) + return xstrndup(buffer + 16, len - 17); + + if(strlen(buffer) == 41) { + /* probably contains a SHA1 sum */ + memset(buffer, 0, sizeof(buffer)); + if(readlink(head, buffer, sizeof(buffer)-1)) { + ref_start = memmem(buffer, sizeof(buffer)-1, "refs/heads/", 11); + if(ref_start) + return xstrdup(ref_start+11); + } + } + return xstrdup("master"); +} + static int prepare_repo_cmd(struct cgit_context *ctx) { char *tmp; @@ -442,10 +473,12 @@ static int prepare_repo_cmd(struct cgit_context *ctx) } ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); + if (!ctx->repo->defbranch) + ctx->repo->defbranch = guess_defbranch(ctx->repo->path); + if (!ctx->qry.head) { ctx->qry.nohead = 1; ctx->qry.head = find_default_branch(ctx->repo); - ctx->repo->defbranch = ctx->qry.head; } if (!ctx->qry.head) { diff --git a/scan-tree.c b/scan-tree.c index a429a9f..378d795 100644 --- a/scan-tree.c +++ b/scan-tree.c @@ -68,39 +68,6 @@ static char *xstrrchr(char *s, char *from, int c) return from < s ? NULL : from; } -static char *guess_defbranch(const char *repo_path) -{ - int fd, len; - char buffer[256]; - char *ref_start; - char *head; - - head = fmt("%s/HEAD", repo_path); - fd = open(head, O_RDONLY); - if (fd == -1) - return xstrdup("master"); - - memset(buffer, 0, sizeof(buffer)); - len = read_in_full(fd, buffer, sizeof(buffer)-1); - close(fd); - - if(!memcmp(buffer, "ref: refs/heads/", 16)) - return xstrndup(buffer+16, len-17); - - if(strlen(buffer) == 41) { - /* probably contains a SHA1 sum */ - memset(buffer, 0, sizeof(buffer)); - if(readlink(head, buffer, sizeof(buffer)-1)) { - ref_start = memmem(buffer, sizeof(buffer)-1, "refs/heads/", 11); - if(ref_start) - return xstrdup(ref_start+11); - } - } - - return xstrdup("master"); -} - - static void add_repo(const char *base, const char *path, repo_config_fn fn) { struct stat st; @@ -138,9 +105,6 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn) *p = '\0'; repo->name = repo->url; repo->path = xstrdup(path); - - repo->defbranch = guess_defbranch(repo->path); - while (!owner) { if ((pwd = getpwuid(st.st_uid)) == NULL) { fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", diff --git a/shared.c b/shared.c index 699c362..9c839a9 100644 --- a/shared.c +++ b/shared.c @@ -56,7 +56,6 @@ struct cgit_repo *cgit_add_repo(const char *url) ret->desc = "[no description]"; ret->owner = NULL; ret->section = ctx.cfg.section; - ret->defbranch = "master"; ret->snapshots = ctx.cfg.snapshots; ret->enable_commit_graph = ctx.cfg.enable_commit_graph; ret->enable_log_filecount = ctx.cfg.enable_log_filecount; -- cgit v1.2.3-70-g09d2 From 8d7c2ec295423fe31d9113038f6717d7b64dbe57 Mon Sep 17 00:00:00 2001 From: Lars Hjemli Date: Mon, 20 Jun 2011 22:52:51 +0000 Subject: cgit.c: use resolve_ref() to guess_defbranch() The resolve_ref() function handles reading of git- and filesystem symbolic links (including proper whitespace trimming) and packed refs. There's no point in reimplementing this function in cgit. Signed-off-by: Lars Hjemli --- cgit.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/cgit.c b/cgit.c index e3fbbf4..624cb2c 100644 --- a/cgit.c +++ b/cgit.c @@ -418,33 +418,13 @@ char *find_default_branch(struct cgit_repo *repo) static char *guess_defbranch(const char *repo_path) { - int fd, len; - char buffer[256]; - char *ref_start; - char *head; - - head = fmt("%s/HEAD", repo_path); - fd = open(head, O_RDONLY); - if (fd == -1) - return xstrdup("master"); - - memset(buffer, 0, sizeof(buffer)); - len = read_in_full(fd, buffer, sizeof(buffer) - 1); - close(fd); - - if(!memcmp(buffer, "ref: refs/heads/", 16)) - return xstrndup(buffer + 16, len - 17); - - if(strlen(buffer) == 41) { - /* probably contains a SHA1 sum */ - memset(buffer, 0, sizeof(buffer)); - if(readlink(head, buffer, sizeof(buffer)-1)) { - ref_start = memmem(buffer, sizeof(buffer)-1, "refs/heads/", 11); - if(ref_start) - return xstrdup(ref_start+11); - } - } - return xstrdup("master"); + const char *ref; + unsigned char sha1[20]; + + ref = resolve_ref("HEAD", sha1, 0, NULL); + if (!ref || prefixcmp(ref, "refs/heads/")) + return "master"; + return xstrdup(ref + 11); } static int prepare_repo_cmd(struct cgit_context *ctx) -- cgit v1.2.3-70-g09d2 From 5293c8b7992bf3211b6bde7acbbd4e74ffd926d4 Mon Sep 17 00:00:00 2001 From: Lars Hjemli Date: Tue, 19 Jul 2011 09:34:18 +0000 Subject: ui-repolist.c: fallback to "master" if no default branch is specified When looking for the modtime of a repo we used to rely on repo.defbranch having a value. This is no longer true so this patch provides a default value when needed. Signed-off-by: Lars Hjemli --- ui-repolist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui-repolist.c b/ui-repolist.c index 25c36ce..f21d28d 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -45,7 +45,8 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime) return 1; } - path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); + path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch ? + repo->defbranch : "master"); if (stat(path, &s) == 0) { *mtime = s.st_mtime; r->mtime = *mtime; -- cgit v1.2.3-70-g09d2