Utoljára aktív 1 day ago

Revízió b2937a980956328a3f99c0ee055c32d640e1b55d

git-clone-path.sh Eredeti
1#!/usr/bin/env bash
2#
3# git-clone-path.sh — clone a shallow Git subdirectory to a target path.
4#
5# Usage:
6# ./git-clone-path.sh [options] <repo_url> <repo_path>
7#
8# Options:
9# -r, --ref <ref> Branch, tag, or commit to check out (default: default branch)
10# -o, --output <dir> Destination directory (default: current directory)
11# -f, --flatten Place the subdirectory's contents directly into <dir>
12# instead of <dir>/<basename>
13# -h, --help Show this help
14#
15# Examples:
16# ./git-clone-path.sh -rmain https://github.com/agent-sh/computer-use-linux \
17# skills/computer-use-linux -o./skills/
18# # -> ./skills/computer-use-linux
19#
20# ./git-clone-path.sh -rmain https://github.com/agent-sh/computer-use-linux \
21# skills/computer-use-linux -o./skills/ -f
22# # -> ./skills/ (contents placed directly)
23
24set -euo pipefail
25
26usage() {
27 sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'
28}
29
30command -v git >/dev/null 2>&1 || { echo "error: git is required but not found" >&2; exit 1; }
31
32REF=""
33OUTPUT=""
34FLATTEN=0
35
36# ---- argument parsing -------------------------------------------------------
37# Options may appear before, between, or after the positional args.
38POSITIONAL=()
39while [[ $# -gt 0 ]]; do
40 case "$1" in
41 -r|--ref)
42 [[ $# -ge 2 ]] || { echo "error: $1 requires a value" >&2; exit 1; }
43 REF="$2"; shift 2 ;;
44 --ref=*) REF="${1#*=}"; shift ;;
45 -r?*) REF="${1#-r}"; shift ;; # -rmain
46 -o|--output)
47 [[ $# -ge 2 ]] || { echo "error: $1 requires a value" >&2; exit 1; }
48 OUTPUT="$2"; shift 2 ;;
49 --output=*) OUTPUT="${1#*=}"; shift ;;
50 -o?*) OUTPUT="${1#-o}"; shift ;; # -o./skills/
51 -f|--flatten) FLATTEN=1; shift ;;
52 -h|--help) usage; exit 0 ;;
53 -*) echo "error: unknown option: $1" >&2; usage >&2; exit 1 ;;
54 *) POSITIONAL+=("$1"); shift ;;
55 esac
56done
57
58if [[ ${#POSITIONAL[@]} -ne 2 ]]; then
59 echo "error: expected <repo_url> and <repo_path>" >&2
60 usage >&2
61 exit 1
62fi
63
64REPO_URL="${POSITIONAL[0]}"
65REPO_PATH="${POSITIONAL[1]#./}" # strip leading ./
66REPO_PATH="${REPO_PATH#/}" # strip leading /
67REPO_PATH="${REPO_PATH%/}" # strip trailing /
68
69# ---- resolve basename & target ---------------------------------------------
70if [[ -z "$REPO_PATH" || "$REPO_PATH" == "." ]]; then
71 REPO_PATH="."
72 BASENAME="$(basename "${REPO_URL%%\?*}" .git)"
73else
74 BASENAME="$(basename "$REPO_PATH")"
75fi
76
77if [[ -n "$OUTPUT" ]]; then
78 OUTDIR="${OUTPUT%/}"
79else
80 OUTDIR="."
81fi
82
83if [[ "$FLATTEN" -eq 1 ]]; then
84 TARGET="$OUTDIR"
85else
86 if [[ -n "$OUTPUT" ]]; then
87 TARGET="$OUTDIR/$BASENAME"
88 else
89 TARGET="$BASENAME"
90 fi
91fi
92
93# ---- shallow sparse clone ---------------------------------------------------
94TMP_DIR="$(mktemp -d)"
95trap 'rm -rf "$TMP_DIR"' EXIT
96
97echo "Cloning $REPO_URL (path: $REPO_PATH) ..."
98git clone --depth 1 --filter=blob:none --no-checkout "$REPO_URL" "$TMP_DIR/repo"
99
100git -C "$TMP_DIR/repo" sparse-checkout init --cone
101git -C "$TMP_DIR/repo" sparse-checkout set "$REPO_PATH"
102
103if [[ -n "$REF" ]]; then
104 git -C "$TMP_DIR/repo" fetch --depth 1 origin "$REF"
105 git -C "$TMP_DIR/repo" checkout --detach FETCH_HEAD
106else
107 git -C "$TMP_DIR/repo" checkout
108fi
109
110SRC="$TMP_DIR/repo/$REPO_PATH"
111if [[ ! -e "$SRC" ]]; then
112 echo "error: path '$REPO_PATH' not found in repository" >&2
113 exit 1
114fi
115
116# ---- place into target ------------------------------------------------------
117if [[ "$FLATTEN" -eq 1 ]]; then
118 mkdir -p "$TARGET"
119 cp -a "$SRC"/. "$TARGET"/
120else
121 mkdir -p "$(dirname "$TARGET")"
122 rm -rf "$TARGET"
123 mv "$SRC" "$TARGET"
124fi
125
126echo "Done -> $TARGET"
127