You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.9 KiB
117 lines
3.9 KiB
const { URL } = require('url');
|
|
|
|
const FALLBACK_DEFAULT_STUDENT_GIT =
|
|
'https://git.educoder.net/pu428f3pz/rnsuwx89z320260422155438.git';
|
|
|
|
/** 与 server 默认学员库一致(可被 DEFAULT_STUDENT_GIT_URL 覆盖) */
|
|
function getDefaultPublicStudentGitUrl() {
|
|
const v = process.env.DEFAULT_STUDENT_GIT_URL;
|
|
return (v && String(v).trim()) || FALLBACK_DEFAULT_STUDENT_GIT;
|
|
}
|
|
|
|
function stripGitCredentials(href) {
|
|
try {
|
|
const u = new URL(String(href).trim());
|
|
u.username = '';
|
|
u.password = '';
|
|
return u.href;
|
|
} catch {
|
|
return String(href).trim();
|
|
}
|
|
}
|
|
|
|
/** 用于判断「是否为同一远程」:忽略凭据、主机小写、去掉末尾 /、可选去掉 .git */
|
|
function normalizeComparableGitRemote(href) {
|
|
try {
|
|
const u = new URL(String(href).trim());
|
|
u.username = '';
|
|
u.password = '';
|
|
u.hostname = u.hostname.toLowerCase();
|
|
let p = u.pathname.replace(/\/+$/, '') || '/';
|
|
if (p.toLowerCase().endsWith('.git')) p = p.slice(0, -4);
|
|
u.pathname = p || '/';
|
|
return `${u.protocol}//${u.hostname}${u.pathname === '/' ? '' : u.pathname}`;
|
|
} catch {
|
|
return stripGitCredentials(href);
|
|
}
|
|
}
|
|
|
|
function sameGitRemoteIgnoringAuth(a, b) {
|
|
return normalizeComparableGitRemote(a) === normalizeComparableGitRemote(b);
|
|
}
|
|
|
|
function hasDefaultGitPasswordAuth() {
|
|
const user = String(process.env.DEFAULT_STUDENT_GIT_USER || '').trim();
|
|
const pass = String(process.env.DEFAULT_STUDENT_GIT_PASSWORD || '').trim();
|
|
return Boolean(user && pass);
|
|
}
|
|
|
|
function shouldApplyDefaultGitAuth(publicGitUrl) {
|
|
if (!hasDefaultGitPasswordAuth()) return false;
|
|
const pub = String(publicGitUrl || '').trim();
|
|
if (!pub) return false;
|
|
const canonicalDefault = getDefaultPublicStudentGitUrl();
|
|
if (!sameGitRemoteIgnoringAuth(pub, canonicalDefault)) return false;
|
|
try {
|
|
const u = new URL(pub);
|
|
if (u.protocol !== 'https:' && u.protocol !== 'http:') return false;
|
|
if (u.username || u.password) return false;
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 供 git clone/pull 使用:当目标与默认学员库为同一远程、且配置了
|
|
* DEFAULT_STUDENT_GIT_USER + DEFAULT_STUDENT_GIT_PASSWORD 时,生成带 userinfo 的 URL。
|
|
* 注意:部分 Git/Credential Manager 会忽略 URL 内嵌密码,此时应配合 buildGitHttpAuthConfigArgs 使用。
|
|
*/
|
|
function resolveCloneUrlForGit(publicGitUrl) {
|
|
const pub = String(publicGitUrl || '').trim();
|
|
if (!pub) return pub;
|
|
if (!shouldApplyDefaultGitAuth(pub)) return pub;
|
|
try {
|
|
const u = new URL(pub);
|
|
const user = String(process.env.DEFAULT_STUDENT_GIT_USER || '').trim();
|
|
const pass = String(process.env.DEFAULT_STUDENT_GIT_PASSWORD || '').trim();
|
|
u.username = user;
|
|
u.password = pass;
|
|
return u.href;
|
|
} catch {
|
|
return pub;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 通过 git -c http.<scheme>//<host>/.extraHeader=Authorization: Basic … 传 HTTPS 凭据,
|
|
* 避免新版 Git / 凭证管理器丢弃 URL 中的 user:password。
|
|
* @returns {string[]} 形如 ['-c', 'http.https://host/.extraHeader=Authorization: Basic xxx']
|
|
*/
|
|
function buildGitHttpAuthConfigArgs(publicGitUrl) {
|
|
if (!shouldApplyDefaultGitAuth(publicGitUrl)) return [];
|
|
try {
|
|
const u = new URL(String(publicGitUrl).trim());
|
|
const user = String(process.env.DEFAULT_STUDENT_GIT_USER || '').trim();
|
|
const pass = String(process.env.DEFAULT_STUDENT_GIT_PASSWORD || '').trim();
|
|
const schemeHost = `${u.protocol}//${u.hostname}`;
|
|
const token = Buffer.from(`${user}:${pass}`, 'utf8').toString('base64');
|
|
const headerVal = `Authorization: Basic ${token}`;
|
|
const configKey = `http.${schemeHost}/.extraHeader`;
|
|
return ['-c', `${configKey}=${headerVal}`];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getDefaultPublicStudentGitUrl,
|
|
stripGitCredentials,
|
|
normalizeComparableGitRemote,
|
|
sameGitRemoteIgnoringAuth,
|
|
resolveCloneUrlForGit,
|
|
buildGitHttpAuthConfigArgs,
|
|
shouldApplyDefaultGitAuth,
|
|
hasDefaultGitPasswordAuth,
|
|
};
|