summaryrefslogtreecommitdiffstats
path: root/save-git.c
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2014-03-12 14:12:58 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2014-03-12 19:41:19 -0700
commit7902af246c5fa2091caf8fd49e592d12b6e26daa (patch)
tree64f0ca570ab05157d0d5bb56d5ab653e4d5b7343 /save-git.c
parent5b3dab719e44f5c20304ed48c5df35f8e115c28b (diff)
downloadsubsurface-7902af246c5fa2091caf8fd49e592d12b6e26daa.tar.gz
Stop using the "git descriptor file" model
Instead, just encode the git repository information in the filename. We want to make it much harder to make it match a real filename, but to still allow easy browsing with the file manager interface. So the git repository "filename" format is the path to the git repository directory, with the branch name encoded as "[branch]" at the end rather than the "path:branch" format that we used in the descriptor file. [ For example, on Windows, a filename like "c:\my.xml" could be interpreted as the branchame "\my.xml" in the repository in the directory "c" ] In particular, with this model, no filename that ends with ".xml" could possibly ever be considered a git repository name, since the last character of a git pathname is always ']'. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'save-git.c')
-rw-r--r--save-git.c90
1 files changed, 47 insertions, 43 deletions
diff --git a/save-git.c b/save-git.c
index 04ff87467..4760fe32a 100644
--- a/save-git.c
+++ b/save-git.c
@@ -854,57 +854,61 @@ static int do_git_save(git_repository *repo, const char *branch, bool select_onl
return 0;
}
-int git_save_dives(int fd, bool select_only)
+/*
+ * If it's not a git repo, return NULL. Be very conservative.
+ */
+struct git_repository *is_git_repository(const char *filename, const char **branchp)
{
- int len, ret;
+ int flen, blen, ret;
struct stat st;
- static char buffer[2048];
git_repository *repo;
char *loc, *branch;
- if (fstat(fd, &st) < 0)
- return 0;
- if (st.st_size >= sizeof(buffer))
- return 0;
- len = st.st_size;
- if (read(fd, buffer, len) != len)
- return 0;
- buffer[len] = 0;
- if (len < 4)
- return 0;
- if (memcmp(buffer, "git ", 4))
- return 0;
-
- /* Ok, it's a git pointer, we're going to follow it */
- close(fd);
-
- /* Trim any whitespace at the end */
- while (isspace(buffer[len-1]))
- buffer[--len] = 0;
-
- /* skip the "git" part and any whitespace from the beginning */
- loc = buffer+3;
- len -= 3;
- while (isspace(*loc)) {
- loc++;
- len--;
- }
+ flen = strlen(filename);
+ if (!flen || filename[--flen] != ']')
+ return NULL;
- if (!len)
- return report_error("Invalid git pointer");
+ /* Find the matching '[' */
+ blen = 0;
+ while (flen && filename[--flen] != '[')
+ blen++;
- /*
- * The result should be a git directory and branch name, like
- * "/home/torvalds/scuba:linus"
- */
- branch = strrchr(loc, ':');
- if (branch)
- *branch++ = 0;
+ if (!flen)
+ return NULL;
+
+ loc = malloc(flen+1);
+ if (!loc)
+ return NULL;
+ memcpy(loc, filename, flen);
+ loc[flen] = 0;
+
+ branch = malloc(blen+1);
+ if (!branch) {
+ free(loc);
+ return NULL;
+ }
+ memcpy(branch, filename+flen+1, blen);
+ branch[blen] = 0;
- if (git_repository_open(&repo, loc))
- return report_error("Unable to open git repository at '%s' (branch '%s')", loc, branch);
+ if (stat(loc, &st) < 0 || !S_ISDIR(st.st_mode)) {
+ free(loc);
+ return NULL;
+ }
- ret = do_git_save(repo, branch, select_only);
+ ret = git_repository_open(&repo, loc);
+ free(loc);
+ if (ret < 0) {
+ free(branch);
+ return NULL;
+ }
+ *branchp = branch;
+ return repo;
+}
+
+int git_save_dives(struct git_repository *repo, const char *branch, bool select_only)
+{
+ int ret = do_git_save(repo, branch, select_only);
git_repository_free(repo);
- return ret < 0 ? ret : 1;
+ free((void *)branch);
+ return ret;
}