آخر نشاط 1 day ago

تعديل 3a03bf2af3ce6e6421b3eb38f9de8d8ee0448d8a

git-clone-path.sh خام
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> (requires -o)
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
64if [[ "$FLATTEN" -eq 1 && -z "$OUTPUT" ]]; then
65 echo "error: -f/--flatten requires -o/--output" >&2
66 exit 1
67fi
68
69REPO_URL="${POSITIONAL[0]}"
70REPO_PATH="${POSITIONAL[1]#./}" # strip leading ./
71REPO_PATH="${REPO_PATH#/}" # strip leading /
72REPO_PATH="${REPO_PATH%/}" # strip trailing /
73
74# ---- resolve basename & target ---------------------------------------------
75if [[ -z "$REPO_PATH" || "$REPO_PATH" == "." ]]; then
76 REPO_PATH="."
77 BASENAME="$(basename "${REPO_URL%%\?*}" .git)"
78else
79 BASENAME="$(basename "$REPO_PATH")"
80fi
81
82if [[ -n "$OUTPUT" ]]; then
83 OUTDIR="${OUTPUT%/}"
84else
85 OUTDIR="."
86fi
87
88if [[ "$FLATTEN" -eq 1 ]]; then
89 TARGET="$OUTDIR"
90else
91 if [[ -n "$OUTPUT" ]]; then
92 TARGET="$OUTDIR/$BASENAME"
93 else
94 TARGET="$BASENAME"
95 fi
96fi
97
98# ---- shallow sparse clone ---------------------------------------------------
99TMP_DIR="$(mktemp -d)"
100trap 'rm -rf "$TMP_DIR"' EXIT
101
102echo "Cloning $REPO_URL (path: $REPO_PATH) ..."
103git clone --depth 1 --filter=blob:none --no-checkout "$REPO_URL" "$TMP_DIR/repo"
104
105git -C "$TMP_DIR/repo" sparse-checkout init --cone
106git -C "$TMP_DIR/repo" sparse-checkout set "$REPO_PATH"
107
108if [[ -n "$REF" ]]; then
109 git -C "$TMP_DIR/repo" fetch --depth 1 origin "$REF"
110 git -C "$TMP_DIR/repo" checkout --detach FETCH_HEAD
111else
112 git -C "$TMP_DIR/repo" checkout
113fi
114
115SRC="$TMP_DIR/repo/$REPO_PATH"
116if [[ ! -e "$SRC" ]]; then
117 echo "error: path '$REPO_PATH' not found in repository" >&2
118 exit 1
119fi
120
121# ---- place into target ------------------------------------------------------
122if [[ "$FLATTEN" -eq 1 ]]; then
123 mkdir -p "$TARGET"
124 cp -a "$SRC"/. "$TARGET"/
125else
126 mkdir -p "$(dirname "$TARGET")"
127 rm -rf "$TARGET"
128 mv "$SRC" "$TARGET"
129fi
130
131echo "Done -> $TARGET"
132