aboutsummaryrefslogtreecommitdiff
path: root/src/cpt-lib.in
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpt-lib.in')
-rw-r--r--src/cpt-lib.in263
1 files changed, 152 insertions, 111 deletions
diff --git a/src/cpt-lib.in b/src/cpt-lib.in
index da84659..5d93f83 100644
--- a/src/cpt-lib.in
+++ b/src/cpt-lib.in
@@ -1663,138 +1663,179 @@ pkg_install() {
log "$pkg_name" "Installed successfully"
}
-pkg_fetch() {
- log "Updating repositories"
-
- run_hook pre-fetch
+pkg_repository_pull_fossil() {
+ # Pull function for Fossil.
+ [ "$(fossil remote 2>/dev/null)" != off ] || {
+ log "$repo" " "
+ printf '%s\n' "No remote, skipping."
+ return 0
+ }
- # Create a list of all repositories.
- # See [1] at top of script.
- # shellcheck disable=2046,2086
- { IFS=:; set -- $CPT_PATH; IFS=$old_ifs ;}
+ # Ensure we have proper permissions to do the pull operation.
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ fossil update
+ else
+ pkg_repository_as_root "fossil update"
+ fi
+}
- # Update each repository in '$CPT_PATH'. It is assumed that
- # each repository is 'git' tracked.
- 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 ||
- cd "$(hg root 2>/dev/null)" 2>/dev/null ||:
+pkg_repository_pull_git() {
+ # Pull function for Git.
+ [ "$(git remote 2>/dev/null)" ] || {
+ log "$repo" " "
+ printf '%s\n' "No remote, skipping."
+ return 0
+ }
- if [ -d .git ]; then
+ # Display a message if signing is enabled for this repository.
+ case $(git config merge.verifySignatures) in
+ true) log "$PWD" "[signed] " ;;
+ *) log "$PWD" " " ;;
+ esac
- [ "$(git remote 2>/dev/null)" ] || {
- log "$repo" " "
- printf '%s\n' "No remote, skipping."
- continue
- }
+ # Ensure we have proper permissions to do the pull operation.
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ git fetch
+ git merge
+ git submodule update --remote --init -f
+ else
+ pkg_repository_as_root \
+ "git fetch && git merge && git submodule update --remote --init -f"
+ fi
+}
- contains "$repos" "$PWD" || {
- repos="$repos $PWD "
+pkg_repository_pull_hg() {
+ # Pull function for Mercurial.
+ [ "$(hg showconfig paths 2>/dev/null)" ] || {
+ log "$repo" " "
+ printf '%s\n' "No remote, skipping."
+ return 0
+ }
- # Display a tick if signing is enabled for this
- # repository.
- case $(git config merge.verifySignatures) in
- true) log "$PWD" "[signed] " ;;
- *) log "$PWD" " " ;;
- esac
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ hg pull
+ hg update
+ else
+ pkg_repository_as_root "hg pull && hg update"
+ fi
+}
- if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
- git fetch
- git merge
- git submodule update --remote --init -f
+pkg_repository_pull_rsync() {
+ # Pull function for rsync repositories. The details of our rsync
+ # repositories are explained in the user manual.
- else
- [ "$uid" = 0 ] || log "$PWD" "Need root to update"
-
- # Find out the owner of the repository and spawn
- # git as this user below.
- #
- # This prevents 'git' from changing the original
- # ownership of files and directories in the rare
- # case that the repository is owned by a 3rd user.
- (
- user=$(_stat "$PWD")
+ # Read remote repository address from the '.rsync' file.
+ read -r remote < .rsync
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ rsync -acvzzC --include=core --delete "$remote/" "$PWD"
+ else
+ pkg_repository_as_root "rsync -acvzzC --include=core --delete \"$remote/\" \"$PWD\""
+ fi
+}
- [ "$user" = root ] ||
- log "Dropping permissions to $user for pull"
+pkg_repository_pull_local() {
+ # Local repository. We don't do a "pull" here, we just notify the user that
+ # this is the case.
+ log "$repo" " "
+ printf '%s\n' "Not a remote repository, skipping."
+}
- git_cmd="git fetch && git merge && git submodule update --remote --init -f"
- case $su in *su) git_cmd="'$git_cmd'"; esac
+pkg_repository_as_root() (
+ # Helper function for pkg_repository_pull* functions used for proper
+ # privilege escalation.
+ [ "$uid" = 0 ] || log "$PWD" "Need root to update"
- # Spawn a subshell to run multiple commands as
- # root at once. This makes things easier on users
- # who aren't using persist/timestamps for auth
- # caching.
- user=$user as_root sh -c "$git_cmd"
- )
- fi
- }
- elif [ -d .hg ]; then
+ # Find out the owner of the repository and spawn the operation as the user
+ # below.
+ #
+ # This prevents the VCS from changing the original ownership of files and
+ # directories in the rare case that the repository is owned by a third user.
+ user=$(_stat "$PWD")
- [ "$(hg showconfig paths 2>/dev/null)" ] || {
- log "$repo" " "
- printf '%s\n' "No remote, skipping."
- continue
- }
+ [ "$user" = root ] || log "Dropping permissions to $user for pull"
+ case ${su##*/} in su) set -- "'$1'"; esac
- contains "$repos $PWD" || {
- repos="$repos $PWD"
+ # Spawn a subhsell to run multiple commands as root at once. This makes
+ # things easier on users who aren't using persist/timestamps for auth
+ # caching.
+ as_root sh -c "$@"
+)
- if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
- hg pull
- hg update
- else
- [ "$uid" ] || log "$PWD" "Need root to update"
+pkg_repository_info() {
+ # Finds and returns repository information for the current directory. It
+ # will return current directory, repository root, and the type of repository
+ # in a colon separated format.
- # We are going to do the same operation as above, to
- # find the owner of the repository.
- (
- user=$(_stat "$PWD")
+ : "${repo_file:=$cac_dir/repository-cache}"
+ set --
- [ "$user" = root ] ||
- log "Dropping permissions to $user for pull"
+ if [ "$CPT_REPO_CACHE" != 0 ] && information=$(grep "^$PWD:" "$repo_file" 2>/dev/null); then
+ # Repository information is already cached.
+ printf '%s\n' "$information" | sed 1q
+ return
+ elif rootdir=$(git rev-parse --show-toplevel 2>/dev/null); then
+ # Git repository
+ backend=git
+ elif rootdir=$(hg root 2>/dev/null); then
+ # Mercurial repository
+ backend=hg
+ elif rootdir=$(fossil info 2>/dev/null | grep ^local-root:); then
+ # Fossil repository
+ backend=fossil
+
+ # We want to remove the initial spacing before the root directory, and
+ # the leading dash on the root directory.
+ rootdir=$(printf '%s\n' "$rootdir" | cut -d ' ' -f2-)
+ rootdir=${rootdir%/}
+ elif [ -f .rsync ]; then
+ backend=rsync
+ rootdir=$PWD
+
+ # If an .rsync_root file exists, we check that the repository root
+ # exists. If it does, we change to that directory to do the fetch.
+ # This way, we allow for partial repositories while making sure that
+ # we can fetch the repository in a single operation.
+ [ -f .rsync_root ] && {
+ read -r rsync_root < .rsync_root
+ [ -f "$rsync_root/.rsync" ] && rootdir=$(_readlinkf "$rsync_root")
+ }
+ else
+ # Local repository
+ backend=local
+ rootdir=$PWD
+ fi
- hg_cmd="hg pull && hg update"
+ # We cache all these information, so that we don't have to spend much time
+ # looking these up the next time we are doing it. If CPT_REPO_CACHE is set
+ # to 0, we will not write this cache.
+ [ "$CPT_REPO_CACHE" = 0 ] || set -- "$repo_file"
+ printf '%s:%s:%s\n' "$PWD" "$rootdir" "$backend" | tee -a "$@"
+}
- case $su in *su) hg_cmd="'$hg_cmd'"; esac
- user=$user as_root sh -c "$hg_cmd"
- )
- fi
- }
- elif [ -f .rsync ]; then
- # If an .rsync_root file exists, we check that the repository root
- # exists. If it does, we change to that directory to do the fetch.
- # This way, we allow for partial repositories while making sure that
- # we can fetch the repository in a single operation.
- [ -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"
+pkg_fetch() {
+ log "Updating repositories"
- # Similar to the git update, we find the owner of
- # the repository and spawn rsync as that user.
- (
- user=$(_stat "$PWD")
+ run_hook pre-fetch
- [ "$user" = root ] ||
- log "Dropping permissions to $user for pull"
+ # Create a list of all repositories.
+ # See [1] at top of script.
+ # shellcheck disable=2046,2086
+ { IFS=:; set -- $CPT_PATH; IFS=$old_ifs ;}
- user=$user as_root rsync -acvzzC --include=core --delete "$remote/" "$PWD"
- )
- fi
- }
- else
- log "$repo" " "
- printf '%s\n' "Not a remote repository, skipping."
- fi
+ # Update each repository in '$CPT_PATH'. It is assumed that
+ # each repository is 'git' tracked.
+ for repo; do
+ # Go to the root of the repository.
+ cd "$repo"
+ repo_type=$(pkg_repository_info)
+ repo_root=${repo_type#$PWD:}
+ repo_type=${repo_type##*:} repo_root=${repo_root%:*}
+ contains "$repos" "$repo_root" || {
+ repos="$repos $repo_root "
+ cd "$repo_root"
+
+ "pkg_repository_pull_$repo_type"
+ }
done
run_hook post-fetch