aboutsummaryrefslogtreecommitdiff
path: root/load/load-with-metadata.in
blob: 01ccd1619b1528159ae2af59cb3f6b83387297f7 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env bash

# file      : load/load-with-metadata.in
# license   : MIT; see accompanying LICENSE file

# The wrapper around brep-load, which pulls the package metadata from a git
# repository and runs brep-load, passing the metadata directory to it.
#
# Specifically, pull a pre-cloned (read-only) git repository with the contents
# of an archive-based bpkg repository. Run brep-load with the `--metadata
# <dir>/owners` option, the --metadata-changed option, if the current snapshot
# of the repository has not yet been processed by brep-load, and forward any
# further arguments to brep-load.
#
# --timeout <seconds>
#
#   Git operation timeout. Specifically, the operation will be aborted if
#   there is no network activity for the specified time. Default is 60
#   seconds. Note that currently the git timeout is only supported for the
#   http(s) transport.
#
# --brep-load <path>
#
#   The brep-load program to be used. This should be the path to the brep-load
#   executable.
#
# Note also that this script maintains the <dir>.load file which contains the
# last successfully processed commit.
#
usage="usage: $0 [<options>] <dir> [<brep-load-args>]"

owd="$(pwd)"
trap "{ cd '$owd'; exit 1; }" ERR
set -o errtrace   # Trap in functions and subshells.
set -o pipefail   # Fail if any pipeline command fails.
shopt -s lastpipe # Execute last pipeline command in the current shell.
shopt -s nullglob # Expand no-match globs to nothing rather than themselves.

@import bpkg-util/utility@ # check_git_connectivity()

# The script's own options.
#
timeout=60
brep_load=

while [[ "$#" -gt 0 ]]; do
  case "$1" in
    --timeout)
      shift
      timeout="$1"
      shift || true
      ;;
    --brep-load)
      shift
      brep_load="$1"
      shift || true
      ;;
    *)
      break
      ;;
  esac
done

# The repository directory.
#
repo_dir="${1%/}"

# Validate options and arguments.
#
if [[ -z "$repo_dir" ]]; then
  error "$usage"
fi

if [[ ! -d "$repo_dir" ]]; then
  error "'$repo_dir' does not exist or is not a directory"
fi

shift # repo_dir

# If brep-load path is not specified, then use the brep-load program from the
# script directory, if present. Otherwise, use the 'brep-load' path.
#
if [[ -z "$brep_load" ]]; then
  brep_load="$(dirname "$(realpath "${BASH_SOURCE[0]}")")/brep-load"

  if [[ ! -x "$brep_load" ]]; then
    brep_load=brep-load
  fi
fi

# Make sure the commit file is present.
#
load_commit="$repo_dir.load"
touch "$load_commit"

# Pull the repository shallowly.
#
if ! remote_url="$(git -C "$repo_dir" config --get remote.origin.url)"; then
  error "'$repo_dir' is not a git repository"
fi

# Save the repository name and branch of where the current commit has been
# fetched from, separated by space. For example 'origin master'.
#
# Note that if the commit belongs to multiple repositories/branches, then we
# extract the first their pair from the git-log output.
#
refs=$(git -C "$repo_dir" log -1 --format=%D)
repo_branch="$(sed -n -E 's%^[^/]+ ([^/ ]+)/([^/ ,]+).*$%\1 \2%p' <<<"$refs")"

if [[ -z "$repo_branch" ]]; then
  error "unable to extract repository and branch from '$refs'"
fi

# Git doesn't support the connection timeout option. The options we use are
# just an approximation of the former, that, in particular, don't cover the
# connection establishing. To work around this problem, before running a git
# command that assumes the remote repository communication we manually check
# connectivity with the remote repository.
#
check_git_connectivity "$remote_url" "$timeout"

# Fail if no network activity happens during the time specified.
#
# Note: keep $repo_branch expansion unquoted.
#
git -c http.lowSpeedLimit=1 -c "http.lowSpeedTime=$timeout" \
  -C "$repo_dir" fetch -q --depth=1 $repo_branch

git -C "$repo_dir" reset -q --hard FETCH_HEAD

# Match the HEAD commit id to the one stored in the file. If it matches, then
# nothing changed in the repository since it has been processed by brep-load
# last time and we should not pass the --metadata-changed option to brep-load.
#
commit="$(git -C "$repo_dir" rev-parse HEAD)"
pc="$(cat "$load_commit")"

loader_options=(--metadata "$repo_dir/owners")

if [[ "$commit" != "$pc" ]]; then
  loader_options+=(--metadata-changed)
fi

"$brep_load" "${loader_options[@]}" "$@"

echo "$commit" >"$load_commit"