Skip to content

Commit 3d36a44

Browse files
docdnpdocdnpfirecow
authored
Enabled download of includes over HTTP (#605) (#958)
* Enabled download of includes over HTTP * Added option --git-over-http (default: false) * When active: Include-Parser uses git spare-checkout instead of git archive * fixed linter problems * autodetecting whether sparse checkout should be preferred * CLI option still available but hidden * Removed CLI option regardin sparse checkout * only auto-detection left over * refactored: parser-includes relies only on git-data * refactored: git-data detects schema on basis of firecow's proposed regexp * fix/workaround: test on invalid project includes passes now * The test attempted to compare an expected error text with the assertion error's message. * The assertion error's message might have changed previously, so the test failed * Analysis of the current logs of failing tests in the pipeline shows that different reasons might lead to an expected failure when calling 'git archive': * the server doesn't exist or isn't reachable (which could timeout), then error message contains - ssh: Could not resolve hostname <non-existing-hostname>: Name or service not known - fatal: the remote end hung up unexpectedly * the credentials for the server are wrong, then error message contains: - [email protected]: Permission denied (publickey). - fatal: the remote end hung up unexpectedly * the repository doesn't exist on the server, then error message contains: - ERROR: The project you were looking for could not be found or you don't have permission to view it. - fatal: the remote end hung up unexpectedly * the file doesn't exist on the server, then error message contains: => remote: fatal: pathspec '.gitlab-modue.yml' did not match any files * Thus it seems OK to test against the 'fatal.*' only * preparing back-merge as discussed with firecow * using clearer if clauses for schema default ports * fixed target path for tar call --------- Co-authored-by: docdnp <[email protected]> Co-authored-by: Mads Jon Nielsen <[email protected]>
1 parent 71360a5 commit 3d36a44

File tree

4 files changed

+158
-11
lines changed

4 files changed

+158
-11
lines changed

package-lock.json

Lines changed: 124 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"jest-when": "3.x.x",
6060
"pkg": "5.x.x",
6161
"ts-jest": "29.x.x",
62+
"ts-node": "^10.9.1",
6263
"typescript": "5.x.x"
6364
},
6465
"engines": {

src/git-data.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class GitData {
1313
};
1414

1515
public readonly remote = {
16+
schema: "git",
1617
port: "22",
1718
host: "gitlab.com",
1819
group: "fallback.group",
@@ -66,11 +67,20 @@ export class GitData {
6667
private async initRemoteData (cwd: string, writeStreams: WriteStreams): Promise<void> {
6768
try {
6869
const {stdout: gitRemote} = await Utils.spawn(["git", "remote", "-v"], cwd);
69-
const gitRemoteMatch = /.*(?:\/\/|@)(?<host>[^:/]*)(:(?<port>\d+)\/|:|\/)(?<group>.*)\/(?<project>[^ .]+)(?:\.git)?.*/.exec(gitRemote);
70+
const gitRemoteMatch = /(?<schema>git|https?)(?::\/\/|@)(?<host>[^:/]*)(:(?<port>\d+)\/|:|\/)(?<group>.*)\/(?<project>[^ .]+)(?:\.git)?.*/.exec(gitRemote);
7071

7172
assert(gitRemoteMatch?.groups != null, "git remote -v didn't provide valid matches");
7273

73-
this.remote.port = gitRemoteMatch.groups.port ?? "22";
74+
this.remote.schema = gitRemoteMatch.groups.schema;
75+
if (this.remote.schema === "git") {
76+
this.remote.port = gitRemoteMatch.groups.port ?? "22";
77+
}
78+
if (this.remote.schema === "https") {
79+
this.remote.port = gitRemoteMatch.groups.port ?? "443";
80+
}
81+
if (this.remote.schema === "http") {
82+
this.remote.port = gitRemoteMatch.groups.port ?? "80";
83+
}
7484
this.remote.host = gitRemoteMatch.groups.host;
7585
this.remote.group = gitRemoteMatch.groups.group;
7686
this.remote.project = gitRemoteMatch.groups.project;

src/parser-includes.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,28 @@ export class ParserIncludes {
164164
const remote = gitData.remote;
165165
const normalizedFile = file.replace(/^\/+/, "");
166166
try {
167-
const target = `${stateDir}/includes/${remote.host}/${project}/${ref}/`;
167+
const target = `${stateDir}/includes/${remote.host}/${project}/${ref}`;
168168
if (await fs.pathExists(`${cwd}/${target}/${normalizedFile}`) && !fetchIncludes) return;
169-
await fs.mkdirp(`${cwd}/${target}`);
170-
await Utils.bash(`git archive --remote=ssh://git@${remote.host}:${remote.port}/${project}.git ${ref} ${normalizedFile} | tar -f - -xC ${target}`, cwd);
169+
170+
if (remote.schema.startsWith("http")) {
171+
const ext = "tmp-" + Math.random();
172+
await fs.ensureFile(`${cwd}/${target}/${normalizedFile}`);
173+
await Utils.bash(`
174+
cd ${cwd}/${stateDir} \
175+
&& git clone -n --depth=1 --filter=tree:0 \
176+
${remote.schema}://${remote.host}/${project}.git \
177+
${cwd}/${target}.${ext} \
178+
&& cd ${cwd}/${target}.${ext} \
179+
&& git sparse-checkout set --no-cone ${normalizedFile} \
180+
&& git checkout \
181+
&& cd ${cwd}/${stateDir} \
182+
&& cp ${cwd}/${target}.${ext}/${normalizedFile}\
183+
${cwd}/${target}/${normalizedFile}
184+
`, cwd);
185+
} else {
186+
await fs.mkdirp(`${cwd}/${target}`);
187+
await Utils.bash(`git archive --remote=ssh://git@${remote.host}:${remote.port}/${project}.git ${ref} ${normalizedFile} | tar -f - -xC ${target}/`, cwd);
188+
}
171189
} catch (e) {
172190
throw new AssertionError({message: `Project include could not be fetched { project: ${project}, ref: ${ref}, file: ${normalizedFile} }\n${e}`});
173191
}

0 commit comments

Comments
 (0)