summaryrefslogtreecommitdiffstats
path: root/src/subgit-init
blob: 7b22344c452f69f03aa5e335a09c10e548c34743 (plain) (blame)
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
#!/bin/bash

# Initializes or updates the bare repository in the subgit container.

usage() {
	die $(cat <<-EOF
	Usage: subgit init [-r] [-f] [-u] [PATH..]

	  Initializes or updates subrepositories by cloning bare repos into
	  .subgit/ and symlinking working directories. Fetches and resets to
	  the tracked commit/branch from .subgitrc.

	  -r  Recursively initialize nested subgit repos
	  -f  Force reset working trees (discards local changes)
	  -u  Update .subgitrc with current commit after init
	EOF
	)
}

recursive=
force=
update=
do_source=1
while [ "$1" ]; do
	case $1 in
	-h) usage;;
	-r) recursive=-r; shift;;
	-u) update=-u; shift;;
	-f) force=-f; shift;;
	-S) do_source=0; shift;;
	--) shift; break;;
	-*) die "Invalid option $1";;
	*) break;;
	esac
done

if [ $do_source -eq 1 ]; then
	root=$(subgit-source root .)
	source "$root/.subgitrc"
fi

readarray -t subrepos < <(subgit-sub subrepo "$@")

for subrepo in "${subrepos[@]}"; do
	echo "$subrepo"

	root=$(subgit-sub parent "$subrepo")
	relpath=$(realpath -m --relative-to="$root" "$subrepo")

	bare="$root/.subgit/$relpath"
	workdir="$root/$relpath"
	test "$workdir" = "$subrepo"

	[ ! -d "$workdir" ] && mkdir -p "$workdir"

	clone=0
	commit=${subgitinfo[$relpath/commit]:-HEAD}
	branch=${subgitinfo[$relpath/branch]}
	if [ ! -d "$bare" ]; then
		clone=1
		mkdir -p "$(dirname "$bare")"
		clone_args=()
		[ ! -z "$branch" ] && clone_args+=(-b "$branch")
		subgit-sub clone "${clone_args[@]}" \
			"${subgitinfo[$relpath/remote]}" "$bare"
	fi

	link_relpath=$(realpath --relative-to="$workdir" "$bare")
	ln -sf "$link_relpath" -T "$workdir/.git"

	if [ ! -z "$branch" ]; then
		fetch_spec=(origin "$branch")
	else
		fetch_spec=(-a)
	fi

	if ! git -C "$workdir" cat-file -e "$commit" 2>/dev/null; then
		git -C "$workdir" fetch "${fetch_spec[@]}"
	fi

	if [ $clone -eq 1 -o ! -z "$force" ]; then
		git -C "$workdir" reset --hard
	fi

	if [ ! -z "$branch" ]; then
		git -C "$workdir" switch "$branch"
	fi

	git -C "$workdir" reset --soft "$commit"
done

if [ ! -z "$update" ]; then
	subgitinfo[$relpath/commit]=$(git -C "$workdir" rev-parse HEAD)
	subgit-source write
fi

for subrepo in "${subrepos[@]}"; do
	if [ ! -z "$recursive" -a -e "$subrepo/.subgitrc" ]; then
		subgit "${sg_flags[@]}" -C "$subrepo" init $force $recursive $update
	fi
done