Reorganize container helper files
Group the Git helper scripts under a container-specific directory so container integration is easier to understand and mount. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
46
container/configure-git.sh
Executable file
46
container/configure-git.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
helper_path="$script_dir/git-credential-hostproxy"
|
||||
scope='global'
|
||||
target_repo=$(pwd)
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--global)
|
||||
scope='global'
|
||||
;;
|
||||
--local)
|
||||
scope='local'
|
||||
;;
|
||||
--repo)
|
||||
shift
|
||||
if [ "$#" -eq 0 ]; then
|
||||
printf 'Missing value for --repo\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
target_repo="$1"
|
||||
;;
|
||||
*)
|
||||
printf 'Usage: %s [--global|--local] [--repo PATH]\n' "$0" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$scope" = 'global' ]; then
|
||||
git config --global --replace-all credential.helper ''
|
||||
git config --global --add credential.helper "$helper_path"
|
||||
git config --global credential.useHttpPath true
|
||||
printf 'Configured global Git credential helper: %s\n' "$helper_path"
|
||||
else
|
||||
git -C "$target_repo" config --local --replace-all credential.helper ''
|
||||
git -C "$target_repo" config --local --add credential.helper "$helper_path"
|
||||
git -C "$target_repo" config --local credential.useHttpPath true
|
||||
printf 'Configured local Git credential helper for %s\n' "$target_repo"
|
||||
fi
|
||||
|
||||
printf 'Proxy URL default: %s\n' "${GIT_CRED_PROXY_URL:-http://host.docker.internal:18765}"
|
||||
printf 'Protocol filter is configured on the host side\n'
|
||||
19
container/git-credential-hostproxy
Executable file
19
container/git-credential-hostproxy
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
|
||||
if [ -n "${GIT_CRED_PROXY_RUNTIME:-}" ]; then
|
||||
exec "$GIT_CRED_PROXY_RUNTIME" "$script_dir/helper.mjs" "$@"
|
||||
fi
|
||||
|
||||
if command -v bun >/dev/null 2>&1; then
|
||||
exec bun "$script_dir/helper.mjs" "$@"
|
||||
fi
|
||||
|
||||
if command -v node >/dev/null 2>&1; then
|
||||
exec node "$script_dir/helper.mjs" "$@"
|
||||
fi
|
||||
|
||||
printf 'Either bun or node is required to run git-credential-hostproxy\n' >&2
|
||||
exit 1
|
||||
98
container/helper.mjs
Normal file
98
container/helper.mjs
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'node:fs/promises';
|
||||
import http from 'node:http';
|
||||
import https from 'node:https';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const operation = process.argv[2] ?? '';
|
||||
const supportedOperations = new Set(['get', 'store', 'erase']);
|
||||
|
||||
if (!supportedOperations.has(operation)) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const proxyUrl = process.env.GIT_CRED_PROXY_URL ?? 'http://host.docker.internal:18765';
|
||||
const tokenFile =
|
||||
process.env.GIT_CRED_PROXY_TOKEN_FILE ?? path.join(__dirname, '..', 'host', 'state', 'token');
|
||||
|
||||
function readStdin() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunks = [];
|
||||
|
||||
process.stdin.on('data', (chunk) => {
|
||||
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
resolve(Buffer.concat(chunks).toString('utf8'));
|
||||
});
|
||||
|
||||
process.stdin.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
function request(url, body, token) {
|
||||
const client = url.protocol === 'https:' ? https : http;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = client.request(
|
||||
url,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
'Content-Length': Buffer.byteLength(body),
|
||||
},
|
||||
},
|
||||
(res) => {
|
||||
const chunks = [];
|
||||
|
||||
res.on('data', (chunk) => {
|
||||
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
resolve({
|
||||
statusCode: res.statusCode ?? 0,
|
||||
body: Buffer.concat(chunks).toString('utf8'),
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
req.on('error', reject);
|
||||
req.end(body);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const token = (process.env.GIT_CRED_PROXY_TOKEN ?? (await fs.readFile(tokenFile, 'utf8'))).trim();
|
||||
const body = await readStdin();
|
||||
const url = new URL(`/${operation}`, proxyUrl);
|
||||
const response = await request(url, body, token);
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
process.stdout.write(response.body);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.body) {
|
||||
process.stderr.write(response.body.trimEnd() + '\n');
|
||||
} else {
|
||||
process.stderr.write(`Proxy request failed with status ${response.statusCode}\n`);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user