aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/cpt.org2
-rw-r--r--docs/cpt.texi2
-rw-r--r--docs/cpt.txt3
-rw-r--r--src/cpt-lib.in263
4 files changed, 159 insertions, 111 deletions
diff --git a/docs/cpt.org b/docs/cpt.org
index 3949cea..0a442d3 100644
--- a/docs/cpt.org
+++ b/docs/cpt.org
@@ -179,6 +179,8 @@ to provide detailed information.
Set the temporary build directory name.
- ~CPT_PROMPT~ ::
If set to 0, =cpt= will not prompt you for anything.
+- ~CPT_REPO_CACHE~ ::
+ If set to 0, =cpt= will not use or write repository information cache.
- ~CPT_ROOT~ ::
If this variable is set, =cpt= will assume the given path as the system root.
- ~CPT_TEST~ ::
diff --git a/docs/cpt.texi b/docs/cpt.texi
index c39b393..0ff0e8d 100644
--- a/docs/cpt.texi
+++ b/docs/cpt.texi
@@ -293,6 +293,8 @@ If set to 1, @samp{cpt} will keep logs regardless of operation success.
Set the temporary build directory name.
@item @code{CPT_PROMPT}
If set to 0, @samp{cpt} will not prompt you for anything.
+@item @code{CPT_REPO_CACHE}
+If set to 0, @samp{cpt} will not use or write repository information cache.
@item @code{CPT_ROOT}
If this variable is set, @samp{cpt} will assume the given path as the system root.
@item @code{CPT_TEST}
diff --git a/docs/cpt.txt b/docs/cpt.txt
index c04a52f..8620539 100644
--- a/docs/cpt.txt
+++ b/docs/cpt.txt
@@ -249,6 +249,9 @@ development manual for *Carbs Packaging Tools*. For development logs see
Set the temporary build directory name.
`CPT_PROMPT'
If set to 0, `cpt' will not prompt you for anything.
+ `CPT_REPO_CACHE'
+ If set to 0, `cpt' will not use or write repository information
+ cache.
`CPT_ROOT'
If this variable is set, `cpt' will assume the given path as the
system root.
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