summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.h7
-rw-r--r--file.c10
-rw-r--r--load-git.c35
-rw-r--r--save-git.c90
-rw-r--r--save-xml.c21
5 files changed, 76 insertions, 87 deletions
diff --git a/dive.h b/dive.h
index febc6080c..5ac43f16d 100644
--- a/dive.h
+++ b/dive.h
@@ -685,8 +685,11 @@ extern void save_dives(const char *filename);
extern void save_dives_logic(const char *filename, bool select_only);
extern void save_dive(FILE *f, struct dive *dive);
extern void export_dives_uddf(const char *filename, const bool selected);
-extern int git_save_dives(int fd, bool select_only);
-extern int git_load_dives(char *where);
+
+struct git_repository;
+extern struct git_repository *is_git_repository(const char *filename, const char **branchp);
+extern int git_save_dives(struct git_repository *, const char *, bool select_only);
+extern int git_load_dives(struct git_repository *, const char *);
extern int subsurface_rename(const char *path, const char *newpath);
extern int subsurface_open(const char *path, int oflags, mode_t mode);
diff --git a/file.c b/file.c
index 826f3eb51..8facdf8d5 100644
--- a/file.c
+++ b/file.c
@@ -356,19 +356,21 @@ static void parse_file_buffer(const char *filename, struct memblock *mem, char *
if (!mem->size || !mem->buffer)
return;
- if (mem->size > 3 && !memcmp(mem->buffer, "git", 3)) {
- git_load_dives(mem->buffer);
- return;
- }
parse_xml_buffer(filename, mem->buffer, mem->size, &dive_table, NULL, error);
}
void parse_file(const char *filename, char **error)
{
+ struct git_repository *git;
+ const char *branch;
struct memblock mem;
char *fmt;
+ git = is_git_repository(filename, &branch);
+ if (git && !git_load_dives(git, branch))
+ return;
+
if (readfile(filename, &mem) < 0) {
/* we don't want to display an error if this was the default file */
if (prefs.default_filename && !strcmp(filename, prefs.default_filename))
diff --git a/load-git.c b/load-git.c
index 15c48027b..5d55245db 100644
--- a/load-git.c
+++ b/load-git.c
@@ -1214,32 +1214,19 @@ static int do_git_load(git_repository *repo, const char *branch)
return ret;
}
-int git_load_dives(char *where)
+/*
+ * Like git_save_dives(), this silently returns a negative
+ * value if it's not a git repository at all (so that you
+ * can try to load it some other way.
+ *
+ * If it is a git repository, we return zero for success,
+ * or report an error and return 1 if the load failed.
+ */
+int git_load_dives(struct git_repository *repo, const char *branch)
{
- int ret, len;
- git_repository *repo;
- char *loc, *branch;
-
- /* Jump over the "git" marker */
- loc = where + 3;
- while (isspace(*loc))
- loc++;
-
- /* Trim whitespace from the end */
- len = strlen(loc);
- while (len && isspace(loc[len-1]))
- loc[--len] = 0;
-
- /* Find a branch name if there is any */
- branch = strrchr(loc, ':');
- if (branch)
- *branch++ = 0;
-
- if (git_repository_open(&repo, loc))
- return report_error("Unable to open git repository at '%s' (branch '%s')", loc, branch);
-
- ret = do_git_load(repo, branch);
+ int ret = do_git_load(repo, branch);
git_repository_free(repo);
+ free((void *)branch);
finish_active_dive();
finish_active_trip();
return ret;
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;
}
diff --git a/save-xml.c b/save-xml.c
index f5d17c49c..a27dcfa76 100644
--- a/save-xml.c
+++ b/save-xml.c
@@ -597,21 +597,14 @@ void save_dives_logic(const char *filename, const bool select_only)
{
struct membuffer buf = { 0 };
FILE *f;
- int fd;
+ void *git;
+ const char *branch;
- /*
- * See if the file already exists, and if so,
- * perhaps it's a git save-file pointer?
- *
- * Otherwise, try to back it up.
- */
- fd = subsurface_open(filename, O_RDONLY, 0);
- if (fd >= 0) {
- if (git_save_dives(fd, select_only))
- return;
- close(fd);
- try_to_backup(filename);
- }
+ git = is_git_repository(filename, &branch);
+ if (git && !git_save_dives(git, branch, select_only))
+ return;
+
+ try_to_backup(filename);
save_dives_buffer(&buf, select_only);