/* * If it's not a git repo, return NULL. Be very conservative. */ struct git_repository *is_git_repository(const char *filename, const char **branchp, const char **remote) { int flen, blen, ret; int offset = 1; struct stat st; git_repository *repo; char *loc, *branch; flen = strlen(filename); if (!flen || filename[--flen] != ']') return NULL; /* Find the matching '[' */ blen = 0; while (flen && filename[--flen] != '[') blen++; /* Ignore slashes at the end of the repo name */ while (flen && filename[flen-1] == '/') { flen--; offset++; } if (!flen) return NULL; /* * This is the "point of no return": the name matches * the git repository name rules, and we will no longer * return NULL. * * We will either return "dummy_git_repository" and the * branch pointer will have the _whole_ filename in it, * or we will return a real git repository with the * branch pointer being filled in with just the branch * name. * * The actual git reading/writing routines can use this * to generate proper error messages. */ *branchp = filename; loc = format_string("%.*s", flen, filename); if (!loc) return dummy_git_repository; branch = format_string("%.*s", blen, filename + flen + offset); if (!branch) { free(loc); return dummy_git_repository; } repo = is_remote_git_repository(loc, branch); if (repo) { if (remote) *remote = loc; else free(loc); *branchp = branch; return repo; } if (stat(loc, &st) < 0 || !S_ISDIR(st.st_mode)) { free(loc); free(branch); return dummy_git_repository; } ret = git_repository_open(&repo, loc); free(loc); if (ret < 0) { free(branch); return dummy_git_repository; } if (remote) *remote = NULL; *branchp = branch; return repo; }
/* * If it's not a git repo, return NULL. Be very conservative. */ struct git_repository *is_git_repository(const char *filename, const char **branchp, const char **remote, bool dry_run) { int flen, blen, ret; int offset = 1; struct stat st; git_repository *repo; char *loc, *branch; flen = strlen(filename); if (!flen || filename[--flen] != ']') return NULL; /* * Special-case "file://", and treat it as a local * repository since libgit2 is insanely slow for that. */ if (!strncmp(filename, "file://", 7)) { filename += 7; flen -= 7; } /* Find the matching '[' */ blen = 0; while (flen && filename[--flen] != '[') blen++; /* Ignore slashes at the end of the repo name */ while (flen && filename[flen-1] == '/') { flen--; offset++; } if (!flen) return NULL; /* * This is the "point of no return": the name matches * the git repository name rules, and we will no longer * return NULL. * * We will either return "dummy_git_repository" and the * branch pointer will have the _whole_ filename in it, * or we will return a real git repository with the * branch pointer being filled in with just the branch * name. * * The actual git reading/writing routines can use this * to generate proper error messages. */ *branchp = filename; loc = format_string("%.*s", flen, filename); if (!loc) return dummy_git_repository; branch = format_string("%.*s", blen, filename + flen + offset); if (!branch) { free(loc); return dummy_git_repository; } if (dry_run) { *branchp = branch; *remote = loc; return dummy_git_repository; } repo = is_remote_git_repository(loc, branch); if (repo) { if (remote) *remote = loc; else free(loc); *branchp = branch; return repo; } if (subsurface_stat(loc, &st) < 0 || !S_ISDIR(st.st_mode)) { if (verbose) fprintf(stderr, "loc %s wasn't found or is not a directory\n", loc); free(loc); free(branch); return dummy_git_repository; } ret = git_repository_open(&repo, loc); free(loc); if (ret < 0) { free(branch); return dummy_git_repository; } if (remote) *remote = NULL; *branchp = branch; return repo; }