1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
#include "clar_libgit2.h"
#include "buffer.h"
#include "path.h"
#include "util.h"
#include "posix.h"
#include "submodule_helpers.h"
#include "git2/sys/repository.h"
/* rewrite gitmodules -> .gitmodules
* rewrite the empty or relative urls inside each module
* rename the .gitted directory inside any submodule to .git
*/
void rewrite_gitmodules(const char *workdir)
{
git_buf in_f = GIT_BUF_INIT, out_f = GIT_BUF_INIT, path = GIT_BUF_INIT;
FILE *in, *out;
char line[256];
cl_git_pass(git_buf_joinpath(&in_f, workdir, "gitmodules"));
cl_git_pass(git_buf_joinpath(&out_f, workdir, ".gitmodules"));
cl_assert((in = fopen(in_f.ptr, "r")) != NULL);
cl_assert((out = fopen(out_f.ptr, "w")) != NULL);
while (fgets(line, sizeof(line), in) != NULL) {
char *scan = line;
while (*scan == ' ' || *scan == '\t') scan++;
/* rename .gitted -> .git in submodule directories */
if (git__prefixcmp(scan, "path =") == 0) {
scan += strlen("path =");
while (*scan == ' ') scan++;
git_buf_joinpath(&path, workdir, scan);
git_buf_rtrim(&path);
git_buf_joinpath(&path, path.ptr, ".gitted");
if (!git_buf_oom(&path) && p_access(path.ptr, F_OK) == 0) {
git_buf_joinpath(&out_f, workdir, scan);
git_buf_rtrim(&out_f);
git_buf_joinpath(&out_f, out_f.ptr, ".git");
if (!git_buf_oom(&out_f))
p_rename(path.ptr, out_f.ptr);
}
}
/* copy non-"url =" lines verbatim */
if (git__prefixcmp(scan, "url =") != 0) {
fputs(line, out);
continue;
}
/* convert relative URLs in "url =" lines */
scan += strlen("url =");
while (*scan == ' ') scan++;
if (*scan == '.') {
git_buf_joinpath(&path, workdir, scan);
git_buf_rtrim(&path);
} else if (!*scan || *scan == '\n') {
git_buf_joinpath(&path, workdir, "../testrepo.git");
} else {
fputs(line, out);
continue;
}
git_path_prettify(&path, path.ptr, NULL);
git_buf_putc(&path, '\n');
cl_assert(!git_buf_oom(&path));
fwrite(line, scan - line, sizeof(char), out);
fputs(path.ptr, out);
}
fclose(in);
fclose(out);
cl_must_pass(p_unlink(in_f.ptr));
git_buf_free(&in_f);
git_buf_free(&out_f);
git_buf_free(&path);
}
static void cleanup_fixture_submodules(void *payload)
{
cl_git_sandbox_cleanup(); /* either "submodules" or "submod2" */
if (payload)
cl_fixture_cleanup(payload);
}
git_repository *setup_fixture_submodules(void)
{
git_repository *repo = cl_git_sandbox_init("submodules");
cl_fixture_sandbox("testrepo.git");
rewrite_gitmodules(git_repository_workdir(repo));
p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git");
cl_set_cleanup(cleanup_fixture_submodules, "testrepo.git");
cl_git_pass(git_repository_reinit_filesystem(repo, 1));
return repo;
}
git_repository *setup_fixture_submod2(void)
{
git_repository *repo = cl_git_sandbox_init("submod2");
cl_fixture_sandbox("submod2_target");
p_rename("submod2_target/.gitted", "submod2_target/.git");
rewrite_gitmodules(git_repository_workdir(repo));
p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git");
p_rename("submod2/not/.gitted", "submod2/not/.git");
cl_set_cleanup(cleanup_fixture_submodules, "submod2_target");
cl_git_pass(git_repository_reinit_filesystem(repo, 1));
return repo;
}