summaryrefslogtreecommitdiff
path: root/src/lib/repo/switch.sh
blob: f411ac2d01ed23133c5320164b41be125504685d (plain)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later

[[ -z ${DEVTOOLS_INCLUDE_REPO_SWITCH_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_REPO_SWITCH_SH=1

_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh

source /usr/share/makepkg/util/message.sh

set -e


pkgctl_repo_switch_usage() {
	local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
	cat <<- _EOF_
		Usage: ${COMMAND} [OPTIONS] [VERSION] [PKGBASE]...

		Switch a package source repository to a specified version, tag or
		branch. The working tree and the index are updated to match the
		specified ref.

		If a version identifier is specified in the pacman version format, that
		identifier is automatically translated to the Git tag name accordingly.

		The current working directory is used if no PKGBASE is specified.

		OPTIONS
		    --discard-changes   Discard changes if index or working tree is dirty
		    -f, --force         An alias for --discard-changes
		    -h, --help          Show this help text

		EXAMPLES
		    $ ${COMMAND} 1.14.6-1 gopass gopass-jsonapi
		    $ ${COMMAND} --force 2:1.19.5-1
		    $ ${COMMAND} main
_EOF_
}

pkgctl_repo_switch() {
	if (( $# < 1 )); then
		pkgctl_repo_switch_usage
		exit 0
	fi

	# options
	local VERSION
	local GIT_REF
	local GIT_CHECKOUT_OPTIONS=()
	local paths path realpath pkgbase

	while (( $# )); do
		case $1 in
			-h|--help)
				pkgctl_repo_switch_usage
				exit 0
				;;
			-f|--force|--discard-changes)
				GIT_CHECKOUT_OPTIONS+=("--force")
				shift
				;;
			--)
				shift
				break
				;;
			-*)
				# - is special to switch back to previous version
				if [[ $1 != - ]]; then
					die "invalid argument: %s" "$1"
				fi
				;;&
			*)
				if [[ -n ${VERSION} ]]; then
					break
				fi
				VERSION=$1
				shift
				;;
		esac
	done

	if [[ -z ${VERSION} ]]; then
		error "missing positional argument 'VERSION'"
		pkgctl_repo_switch_usage
		exit 1
	fi

	GIT_REF="$(get_tag_from_pkgver "${VERSION}")"
	paths=("$@")

	# check if invoked without any path from within a packaging repo
	if (( ${#paths[@]} == 0 )); then
		if [[ -f PKGBUILD ]]; then
			paths=(".")
		else
			die "Not a package repository: $(realpath -- .)"
		fi
	fi

	for path in "${paths[@]}"; do
		if ! realpath=$(realpath -e -- "${path}"); then
			die "No such directory: ${path}"
		fi
		pkgbase=$(basename "${realpath}")

		if [[ ! -d "${path}/.git" ]]; then
			error "Not a Git repository: ${path}"
			continue
		fi

		if ! git -C "${path}" checkout "${GIT_CHECKOUT_OPTIONS[@]}" "${GIT_REF}"; then
			die "Failed to switch ${pkgbase} to version ${VERSION}"
		fi
		msg "Successfully switched ${pkgbase} to version ${VERSION}"
	done
}