From 2893ed3c36ff95f548df44071fa2fb3bdd27cbf5 Mon Sep 17 00:00:00 2001 From: merakor Date: Mon, 31 Aug 2020 21:19:22 +0000 Subject: cpt-lib: repository and source revamp. See log. Many additions and changes here, - added support for Mercurial sources - added support for Mercurial repositories - adapted git source changes from kiss - Changed rsync repository behaviour: A new file has been added to rsync repositories: .rsync_root This file points to the repository root. If the directory that .rsync_root points also has an '.rsync' file, this will be accepted as the root directory and the rsync operation will take place on the root. This ensures that we can have repository exchanges on a single rsync call, while still allowing for partial repositories. FossilOrigin-Name: ddc0b35ae230e0ac43ac0b10fa541aa577496c38f90c327210300110360f5afc --- src/cpt-lib | 174 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 86 insertions(+), 88 deletions(-) diff --git a/src/cpt-lib b/src/cpt-lib index db7f26a..55b1b2b 100644 --- a/src/cpt-lib +++ b/src/cpt-lib @@ -514,61 +514,14 @@ pkg_sources() { repo_dir=$(pkg_find "$1") while read -r src dest || [ "$src" ]; do - # Comment. - if [ -z "${src##\#*}" ]; then : + # Remote git/hg repository or comment. + if [ -z "${src##\#*}" ] || [ -z "${src##git+*}" ] || [ -z "${src##hg+*}" ] + then : # Remote source (cached). elif [ -f "${src##*/}" ]; then log "$1" "Found cached source '${src##*/}'" - # Remote git repository. - elif [ -z "${src##git+*}" ]; then - # This is a checksums check, skip it. - [ "$2" ] && continue - - # Since git is an optional dependency, make sure - # it is available on the system. - command -v git >/dev/null || - die "git must be installed in order to acquire ${src##git+}" - - mkdir -p "$mak_dir/$1/$dest" - - # Run in a subshell to keep the variables, path and - # argument list local to each loop iteration. - ( - repo_src=${src##git+} - - log "$1" "Cloning ${repo_src%[@#]*}" - - # Git has no option to clone a repository to a - # specific location so we must do it ourselves - # beforehand. - cd "$mak_dir/$1/$dest" 2>/dev/null || die - - # Clear the argument list as we'll be overwriting - # it below based on what kind of checkout we're - # dealing with. - set -- "$repo_src" - - # If a branch was given, shallow clone it directly. - # This speeds things up as we don't have to grab - # a lot of unneeded commits. - [ "${src##*@*}" ] || - set -- -b "${src##*@}" "${repo_src%@*}" - - # Maintain compatibility with older versions of - # cpt by shallow cloning all branches. This has - # the added benefit of allowing checkouts of - # specific commits in specific branches. - [ "${src##*#*}" ] || - set -- --no-single-branch "${repo_src%#*}" - - # Always do a shallow clone as we will unshallow it if - # needed later (when a commit is desired). - git clone --depth=1 "$@" . - - ) || die "$1" "Failed to clone $src" - # Remote source. elif [ -z "${src##*://*}" ]; then log "$1" "Downloading $src" @@ -591,31 +544,43 @@ pkg_sources() { pkg_extract() { # Extract all source archives to the build directory and copy over # any local repository files. - log "$1" "Extracting sources" - repo_dir=$(pkg_find "$1") + # Support packages without sources. Simply do nothing. + [ -f "$repo_dir/sources" ] || return 0 + + log "$1" "Extracting sources" + while read -r src dest || [ "$src" ]; do mkdir -p "$mak_dir/$1/$dest" && cd "$mak_dir/$1/$dest" case $src in - # Git repository with supplied commit hash. - git+*\#*) - log "Checking out ${src##*#}" - - # A commit was requested, unshallow the repository. - # This will convert it to a regular repository with - # full history. - git fetch --unshallow - - # Try to checkout the repository. If we fail here, - # the requested commit doesn't exist. - git -c advice.detachedHead=false checkout "${src##*#}" || - die "Commit hash ${src##*#} doesn't exist" + # Git repository. + git+*) + # Split the source into URL + OBJECT (branch or commit). + url=${src##git+} com=${url##*[@#]} com=${com#${url%[@#]*}} + + log "$1" "Cloning ${url%[@#]*}"; { + git init + git remote add origin "${url%[@#]*}" + git fetch --depth=1 origin "$com" || git fetch + git checkout "${com:-FETCH_HEAD}" + } || die "$1" "Failed to clone $src" ;; - # Git repository, comment or blank line. - git+*|\#*|'') continue ;; + # Mercurial repository. + hg+*) + # Split the source into URL + OBJECT (branch or commit). + url=${src##hg+} com=${url##*[@#]} com=${com#${url%[@#]*}} + + # Unfortunately, there is no shallow cloning with Mercurial. + log "$1" "Cloning ${url%[@#]*}" + hg clone -u "${com:-tip}" + + ;; + + # Comment or blank line. + \#*|'') continue ;; # Only 'tar' an 'zip' archives are currently supported for # extraction. Other filetypes are simply copied to '$mak_dir' @@ -1529,7 +1494,7 @@ pkg_fetch() { # Update each repository in '$CPT_PATH'. It is assumed that # each repository is 'git' tracked. - for repo do + for repo; do # Go to the root of the repository (if it exists). cd "$repo" cd "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null ||: @@ -1554,7 +1519,7 @@ pkg_fetch() { # Display a tick if signing is enabled for this # repository. case $(git config merge.verifySignatures) in - true) log "$PWD" "[signed ✓] " ;; + true) log "$PWD" "[signed] " ;; *) log "$PWD" " " ;; esac @@ -1573,7 +1538,7 @@ pkg_fetch() { # ownership of files and directories in the rare # case that the repository is owned by a 3rd user. ( - user=$(cpt-stat "$PWD") || user=root + user=$(cpt-stat "$PWD") || user=root id -u "$user" >/dev/null 2>&1 || user=root [ "$user" = root ] || @@ -1590,25 +1555,58 @@ pkg_fetch() { ) fi } + elif hg root >/dev/null 2>&1; then + cd "$(hg root)" + contains "$repos $PWD" || { + repos="$repos $PWD" + if [ -w "$PWD" ] && [ "$uid" != 0 ]; then + hg pull + hg update + else + [ "$uid" ] || log "$PWD" "Need root to update" + + # We are going to do the same operation as above, to + # find the owner of the repository. + ( + user=$(cpt-stat "$PWD") || user=root + id -u "$user" >/dev/null 2>&1 || user=root + + [ "$user" = root ] || + log "Dropping permissions to $user for pull" + + hg_cmd="hg pull && hg update" + + case $su in *su) hg_cmd="'$hg_cmd'"; esac + user=$user as_root sh -c "$hg_cmd" + ) + fi + } elif [ -f .rsync ]; then - read -r remote < .rsync - if [ -w "$PWD" ] && [ "$uid" != 0 ]; then - rsync -acvzzC --include=core --delete "$remote/" "$PWD" - else - [ "$uid" = 0 ] || log "$PWD" "Need root to update" - - # Similar to the git update, we find the owner of - # the repository and spawn rsync as that user. - ( - user=$(cpt-stat "$PWD") || user=root - id -u "$user" >/dev/null 2>&1 || user=root - - [ "$user" = root ] || - log "Dropping permissions to $user for pull" - - user=$user as_root rsync -acvzzC --include=core --delete "$remote/" "$PWD" - ) - fi + [ -f .rsync_root ] && { + read -r rsync_root < .rsync_root + [ -f "$rsync_root/.rsync" ] && cd "$rsync_root" + } + contains "$repos" "$PWD" || { + repos="$repos $PWD" + read -r remote < .rsync + if [ -w "$PWD" ] && [ "$uid" != 0 ]; then + rsync -acvzzC --include=core --delete "$remote/" "$PWD" + else + [ "$uid" = 0 ] || log "$PWD" "Need root to update" + + # Similar to the git update, we find the owner of + # the repository and spawn rsync as that user. + ( + user=$(cpt-stat "$PWD") || user=root + id -u "$user" >/dev/null 2>&1 || user=root + + [ "$user" = root ] || + log "Dropping permissions to $user for pull" + + user=$user as_root rsync -acvzzC --include=core --delete "$remote/" "$PWD" + ) + fi + } else log "$repo" " " printf '%s\n' "Not a remote repository, skipping." -- cgit v1.2.3