diff options
-rw-r--r-- | dive.h | 7 | ||||
-rw-r--r-- | file.c | 10 | ||||
-rw-r--r-- | load-git.c | 35 | ||||
-rw-r--r-- | save-git.c | 90 | ||||
-rw-r--r-- | save-xml.c | 21 |
5 files changed, 76 insertions, 87 deletions
@@ -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); @@ -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); |