|
|
@ -127,7 +127,7 @@ function main() {
|
|
|
|
;;
|
|
|
|
;;
|
|
|
|
-l) # used by decrypt()
|
|
|
|
-l) # used by decrypt()
|
|
|
|
DO_LIST="YES"
|
|
|
|
DO_LIST="YES"
|
|
|
|
[ "$YADM_COMMAND" = "config" ] && YADM_ARGS+=("$1")
|
|
|
|
[[ "$YADM_COMMAND" =~ ^(clone|config)$ ]] && YADM_ARGS+=("$1")
|
|
|
|
;;
|
|
|
|
;;
|
|
|
|
-w) # used by init() and clone()
|
|
|
|
-w) # used by init() and clone()
|
|
|
|
if [[ ! "$2" =~ ^/ ]] ; then
|
|
|
|
if [[ ! "$2" =~ ^/ ]] ; then
|
|
|
@ -705,84 +705,74 @@ function clean() {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _default_remote_branch() {
|
|
|
|
|
|
|
|
local ls_remote
|
|
|
|
|
|
|
|
ls_remote=$("$GIT_PROGRAM" ls-remote -q --symref "$1" 2>/dev/null)
|
|
|
|
|
|
|
|
match="^ref:[[:blank:]]+refs/heads/([^[:blank:]]+)"
|
|
|
|
|
|
|
|
if [[ "$ls_remote" =~ $match ]] ; then
|
|
|
|
|
|
|
|
echo "${BASH_REMATCH[1]}"
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
echo master
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function clone() {
|
|
|
|
function clone() {
|
|
|
|
|
|
|
|
|
|
|
|
DO_BOOTSTRAP=1
|
|
|
|
DO_BOOTSTRAP=1
|
|
|
|
local branch=
|
|
|
|
local -a args
|
|
|
|
|
|
|
|
local -i do_checkout=1
|
|
|
|
local repo_url=
|
|
|
|
|
|
|
|
while [[ $# -gt 0 ]] ; do
|
|
|
|
while [[ $# -gt 0 ]] ; do
|
|
|
|
key="$1"
|
|
|
|
case "$1" in
|
|
|
|
case $key in
|
|
|
|
|
|
|
|
-b)
|
|
|
|
|
|
|
|
if ! is_valid_branch_name "$2"; then
|
|
|
|
|
|
|
|
error_out "You must provide a branch name when using '-b'"
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
branch="$2"
|
|
|
|
|
|
|
|
shift
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
--bootstrap) # force bootstrap, without prompt
|
|
|
|
--bootstrap) # force bootstrap, without prompt
|
|
|
|
DO_BOOTSTRAP=2
|
|
|
|
DO_BOOTSTRAP=2
|
|
|
|
;;
|
|
|
|
;;
|
|
|
|
--no-bootstrap) # prevent bootstrap, without prompt
|
|
|
|
--no-bootstrap) # prevent bootstrap, without prompt
|
|
|
|
DO_BOOTSTRAP=3
|
|
|
|
DO_BOOTSTRAP=3
|
|
|
|
;;
|
|
|
|
;;
|
|
|
|
*) # use first found argument as the URL
|
|
|
|
--checkout)
|
|
|
|
[ -z "$repo_url" ] && repo_url="$1"
|
|
|
|
do_checkout=1
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
-n|--no-checkout)
|
|
|
|
|
|
|
|
do_checkout=0
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
--bare|--mirror|--recurse-submodules*|--recursive|--separate-git-dir=*)
|
|
|
|
|
|
|
|
# ignore arguments without separate parameter
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
--separate-git-dir)
|
|
|
|
|
|
|
|
# ignore arguments with separate parameter
|
|
|
|
|
|
|
|
shift
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
*)
|
|
|
|
|
|
|
|
args+=("$1")
|
|
|
|
;;
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
[ -z "$repo_url" ] && error_out "No repository provided"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ -z "$branch" ] && branch=$(_default_remote_branch "$repo_url")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ -n "$DEBUG" ] && display_private_perms "initial"
|
|
|
|
[ -n "$DEBUG" ] && display_private_perms "initial"
|
|
|
|
|
|
|
|
|
|
|
|
# shellcheck disable=SC2119
|
|
|
|
# safety check, don't attempt to clone when the repo is already present
|
|
|
|
# clone will begin with a bare repo
|
|
|
|
[ -d "$YADM_REPO" ] && [ -z "$FORCE" ] &&
|
|
|
|
init
|
|
|
|
error_out "Git repo already exists. [$YADM_REPO]\nUse '-f' if you want to force it to be overwritten."
|
|
|
|
|
|
|
|
|
|
|
|
# configure local HEAD with the correct branch
|
|
|
|
|
|
|
|
printf 'ref: refs/heads/%s\n' "$branch" > "${YADM_REPO}/HEAD"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# add the specified remote, and configure the repo to track origin/$branch
|
|
|
|
|
|
|
|
debug "Adding remote to new repo"
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" remote add origin "$repo_url"
|
|
|
|
|
|
|
|
debug "Configuring new repo to track origin/${branch}"
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" config "branch.${branch}.remote" origin
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" config "branch.${branch}.merge" "refs/heads/${branch}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# fetch / merge (and possibly fallback to reset)
|
|
|
|
# remove existing if forcing the clone to happen anyway
|
|
|
|
debug "Doing an initial fetch of the origin"
|
|
|
|
[ -d "$YADM_REPO" ] && {
|
|
|
|
"$GIT_PROGRAM" fetch origin || {
|
|
|
|
debug "Removing existing repo prior to clone"
|
|
|
|
debug "Removing repo after failed clone"
|
|
|
|
"$GIT_PROGRAM" -C "$YADM_WORK" submodule deinit -f --all
|
|
|
|
rm -rf "$YADM_REPO"
|
|
|
|
rm -rf "$YADM_REPO"
|
|
|
|
error_out "Unable to fetch origin $repo_url"
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
debug "Verifying '${branch}' is a valid branch to merge"
|
|
|
|
|
|
|
|
[ -f "${YADM_REPO}/refs/remotes/origin/${branch}" ] || {
|
|
|
|
local wc
|
|
|
|
|
|
|
|
wc="$(mktemp -d)" || error_out "Unable to create temporary directory"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# first clone without checkout
|
|
|
|
|
|
|
|
debug "Doing an initial clone of the repository"
|
|
|
|
|
|
|
|
(cd "$wc" &&
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" -c core.sharedrepository=0600 clone --no-checkout \
|
|
|
|
|
|
|
|
--separate-git-dir="$YADM_REPO" "${args[@]}" repo.git) || {
|
|
|
|
debug "Removing repo after failed clone"
|
|
|
|
debug "Removing repo after failed clone"
|
|
|
|
rm -rf "$YADM_REPO"
|
|
|
|
rm -rf "$YADM_REPO" "$wc"
|
|
|
|
error_out "Clone failed, 'origin/${branch}' does not exist in $repo_url"
|
|
|
|
error_out "Unable to clone the repository"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rm -rf "$wc"
|
|
|
|
|
|
|
|
configure_repo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# then reset the index as the --no-checkout flag makes the index empty
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" reset --quiet -- .
|
|
|
|
|
|
|
|
|
|
|
|
if [ "$YADM_WORK" = "$HOME" ]; then
|
|
|
|
if [ "$YADM_WORK" = "$HOME" ]; then
|
|
|
|
debug "Determining if repo tracks private directories"
|
|
|
|
debug "Determining if repo tracks private directories"
|
|
|
|
for private_dir in $(private_dirs all); do
|
|
|
|
for private_dir in $(private_dirs all); do
|
|
|
|
found_log=$("$GIT_PROGRAM" log -n 1 "origin/${branch}" -- "$private_dir" 2>/dev/null)
|
|
|
|
found_log=$("$GIT_PROGRAM" log -n 1 -- "$private_dir" 2>/dev/null)
|
|
|
|
if [ -n "$found_log" ]; then
|
|
|
|
if [ -n "$found_log" ]; then
|
|
|
|
debug "Private directory $private_dir is tracked by repo"
|
|
|
|
debug "Private directory $private_dir is tracked by repo"
|
|
|
|
assert_private_dirs "$private_dir"
|
|
|
|
assert_private_dirs "$private_dir"
|
|
|
@ -790,51 +780,33 @@ function clone() {
|
|
|
|
done
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
[ -n "$DEBUG" ] && display_private_perms "pre-merge"
|
|
|
|
# finally check out (unless instructed not to) all files that don't exist in $YADM_WORK
|
|
|
|
debug "Doing an initial merge of origin/${branch}"
|
|
|
|
if [[ $do_checkout -ne 0 ]]; then
|
|
|
|
"$GIT_PROGRAM" merge "origin/${branch}" || {
|
|
|
|
[ -n "$DEBUG" ] && display_private_perms "pre-checkout"
|
|
|
|
debug "Merge failed, doing a reset and stashing conflicts."
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" reset "origin/${branch}"
|
|
|
|
|
|
|
|
if cd "$YADM_WORK"; then # necessary because of a bug in Git
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" -c user.name='yadm clone' -c user.email='yadm' stash save Conflicts preserved from yadm clone command 2>&1
|
|
|
|
|
|
|
|
cat <<EOF
|
|
|
|
|
|
|
|
**NOTE**
|
|
|
|
|
|
|
|
Merging origin/${branch} failed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
As a result, yadm did 'reset origin/${branch}', and then
|
|
|
|
cd_work "Clone" || return
|
|
|
|
stashed the conflicting data.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This likely happened because you had files in \$HOME
|
|
|
|
"$GIT_PROGRAM" ls-files --deleted | while IFS= read -r file; do
|
|
|
|
which conflicted with files tracked by origin/${branch}.
|
|
|
|
"$GIT_PROGRAM" checkout -- ":/$file"
|
|
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
You can review the stashed conflicts with the
|
|
|
|
if [ -n "$("$GIT_PROGRAM" ls-files --modified)" ]; then
|
|
|
|
command 'yadm stash show -p' from within your
|
|
|
|
|
|
|
|
\$HOME directory. If you want to restore the
|
|
|
|
|
|
|
|
stashed data, you can run 'yadm stash apply' or
|
|
|
|
|
|
|
|
'yadm stash pop' and then handle the conflicts
|
|
|
|
|
|
|
|
in another way.
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
# skip auto_bootstrap if conflicts could not be stashed
|
|
|
|
|
|
|
|
DO_BOOTSTRAP=0
|
|
|
|
|
|
|
|
cat <<EOF
|
|
|
|
cat <<EOF
|
|
|
|
**NOTE**
|
|
|
|
**NOTE**
|
|
|
|
Merging origin/${branch} failed.
|
|
|
|
Local files with content that differs from the ones just
|
|
|
|
yadm did 'reset origin/${branch}' instead.
|
|
|
|
cloned were found in $YADM_WORK. They have been left
|
|
|
|
|
|
|
|
unmodified.
|
|
|
|
yadm did not stash these conflicts beacuse it was unable
|
|
|
|
|
|
|
|
to change to the $YADM_WORK directory.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Please review and resolve any differences appropriately
|
|
|
|
Please review and resolve any differences appropriately.
|
|
|
|
If you know what you're doing, and want to overwrite the
|
|
|
|
If you know what you're doing, and want to overwrite the
|
|
|
|
tracked files, consider 'yadm reset --hard origin/${branch}'
|
|
|
|
tracked files, consider 'yadm checkout "$YADM_WORK"'.
|
|
|
|
EOF
|
|
|
|
EOF
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ -n "$DEBUG" ] && display_private_perms "post-merge"
|
|
|
|
[ -n "$DEBUG" ] && display_private_perms "post-checkout"
|
|
|
|
|
|
|
|
|
|
|
|
CHANGES_POSSIBLE=1
|
|
|
|
CHANGES_POSSIBLE=1
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1158,6 +1130,7 @@ function init() {
|
|
|
|
# remove existing if forcing the init to happen anyway
|
|
|
|
# remove existing if forcing the init to happen anyway
|
|
|
|
[ -d "$YADM_REPO" ] && {
|
|
|
|
[ -d "$YADM_REPO" ] && {
|
|
|
|
debug "Removing existing repo prior to init"
|
|
|
|
debug "Removing existing repo prior to init"
|
|
|
|
|
|
|
|
"$GIT_PROGRAM" -C "$YADM_WORK" submodule deinit -f --all
|
|
|
|
rm -rf "$YADM_REPO"
|
|
|
|
rm -rf "$YADM_REPO"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1459,18 +1432,6 @@ function exclude_encrypted() {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function is_valid_branch_name() {
|
|
|
|
|
|
|
|
# Git branches do not allow:
|
|
|
|
|
|
|
|
# * path component that begins with "."
|
|
|
|
|
|
|
|
# * double dot
|
|
|
|
|
|
|
|
# * "~", "^", ":", "\", space
|
|
|
|
|
|
|
|
# * end with a "/"
|
|
|
|
|
|
|
|
# * end with ".lock"
|
|
|
|
|
|
|
|
pattern='(\/\.|\.\.|[~^:\\ ]|\/$|\.lock$)'
|
|
|
|
|
|
|
|
[[ "$1" =~ $pattern ]] && return 1
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function query_distro() {
|
|
|
|
function query_distro() {
|
|
|
|
distro=""
|
|
|
|
distro=""
|
|
|
|
if command -v "$LSB_RELEASE_PROGRAM" &> /dev/null; then
|
|
|
|
if command -v "$LSB_RELEASE_PROGRAM" &> /dev/null; then
|
|
|
|