Repository navigation
Expand file tree
/
Copy pathgithub.ts
More file actions
144 lines (128 loc) · 3.95 KB
/
Copy pathgithub.ts
File metadata and controls
144 lines (128 loc) · 3.95 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* github.ts
*
* Copyright (C) 2021-2023 Posit Software, PBC
*/
import { which } from "./path.ts";
import { execProcess } from "./process.ts";
import { join } from "../deno_ral/path.ts";
import { existsSync } from "../deno_ral/fs.ts";
import { isHttpUrl } from "./url.ts";
import { GitHubContext } from "./github-types.ts";
import { gitBranchExists } from "./git.ts";
export async function gitHubContext(dir: string) {
// establish dir
const context: GitHubContext = {
git: false,
repo: false,
};
// check for git
context.git = !!(await which("git"));
// check for a repo in this directory
if (context.git) {
context.repo = (await execProcess({
cmd: "git",
args: ["rev-parse"],
cwd: dir,
stdout: "piped",
stderr: "piped",
})).success;
// check for an origin remote
if (context.repo) {
const result = await execProcess({
cmd: "git",
args: ["config", "--get", "remote.origin.url"],
cwd: dir,
stdout: "piped",
stderr: "piped",
});
if (result.success) {
context.originUrl = result.stdout?.trim();
// check for a gh-pages branch
const ghPagesRemote = await execProcess({
cmd: "git",
args: [
"ls-remote",
"--quiet",
"--exit-code",
"origin",
"gh-pages",
],
stdout: "piped",
stderr: "piped",
});
context.ghPagesRemote = ghPagesRemote.success;
if (!ghPagesRemote.success) {
// when no gh-pages branch on remote, check local to avoid creation error
// as if local branch exists, we don't want to create a new one
// https://git-scm.com/docs/git-ls-remote#Documentation/git-ls-remote.txt---exit-code
if (ghPagesRemote.code === 2) {
context.ghPagesLocal = await gitBranchExists("gh-pages");
} else {
// if we go there, this means something is not right with the remote origin
throw new Error(
`There is an error while retrieving information from remote 'origin'.\n Git error: ${ghPagesRemote.stderr}. \n Git status code: ${ghPagesRemote.code}.`,
);
}
}
// determine siteUrl
context.siteUrl = siteUrl(
dir,
context.originUrl!,
);
const repo = repoInfo(context.originUrl!);
if (repo) {
context.repoUrl = repo.repoUrl;
context.organization = repo.organization;
context.repository = repo.repository;
}
}
}
}
return context;
}
const kGithubCom = "github.com";
const kGithubIo = "github.io";
const kGithubGitPattern = /^git@([^:]+):([^\/]+)\/(.+?)(?:\.git)?$/;
const kGithubHttpsPattern = /^https:\/\/([^\/]+)\/([^\/]+)\/(.+?)(?:\.git)?$/;
function repoInfo(originUrl: string) {
// pick apart origin url for github.com
const match = originUrl?.match(kGithubGitPattern) ||
originUrl?.match(kGithubHttpsPattern);
if (match && match.includes(kGithubCom)) {
return {
repoUrl: `https://${match[1]}/${match[2]}/${match[3]}/`,
organization: match[2],
repository: match[3],
};
}
}
function siteUrl(
dir: string,
originUrl: string,
) {
// check for CNAME file
const cname = join(dir, "CNAME");
if (existsSync(cname)) {
const url = Deno.readTextFileSync(cname).trim();
if (isHttpUrl(url)) {
return url;
} else {
return `https://${url}`;
}
} else {
// pick apart origin url for github.com
const match = originUrl?.match(kGithubGitPattern) ||
originUrl?.match(kGithubHttpsPattern);
if (match && match.includes(kGithubCom)) {
const server = match[1].replace(kGithubCom, kGithubIo);
const domain = `${match[2]}.${server}`;
// user's root site uses just the domain
if (domain === match[3]) {
return `https://${domain}/`;
} else {
return `https://${domain}/${match[3]}/`;
}
}
}
}