summaryrefslogtreecommitdiff
path: root/bin/repo-copy
blob: 803cae3f8e106b5c62a63f1c7a1d2e2e19f9a09b (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
#!/bin/sh

# Rudimentary copy a package from one repository to another.
# Note, that we do _not_ need to have the package itself, since all
# relevant information is already in the original package database.

# "Rudimentary" means the following restrictions:
#   - no arguments are accepted
#   - no database signatures are handled
#   - only *.db.tar.gz and *.files.tar.gz are recognized as database

# shellcheck disable=SC2119,SC2120

usage() {
  >&2 echo 'usage:'
  >&2 echo ' repo-copy from-repo.db.tar.gz to-repo.db.tar.gz package1 package2 ...'
  >&2 echo
  >&2 echo 'Note, that the packages must be given with version, e.g. "linux-4.15.7-1.0".'
  exit 2
}

if [ $# -le 2 ]; then
  usage
fi

from_repo="$1"
to_repo="$2"
shift
shift

tmp_dir=$(mktemp -d "${TMPDIR:-/tmp}/repo-tools.XXXXXXXXXX")
trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT

# extract the databases
for repo in 'from' 'to'; do
  for archive in 'db' 'files'; do
    eval 'repo_db="${'"${repo}"'_repo}"'
    if [ "${repo_db}" = "${repo_db%.db.tar.gz}" ]; then
      >&2 printf '"%s" has an invalid suffix.\n' "${repo_db}"
      usage
    fi
    if [ "${archive}" = 'files' ]; then
      repo_db="${repo_db%.db.tar.gz}.files.tar.gz"
    fi
    if [ ! -f "${repo_db}" ]; then
      >&2 printf 'Cannot open file "%s".\n' "${repo_db}"
      usage
    fi
    mkdir "${tmp_dir}/${repo}.${archive}"
    bsdtar -C "${tmp_dir}/${repo}.${archive}" -xf "${repo_db}"
  done
done

# move the packages
for package in "$@"; do
  errors=$(
    find "${tmp_dir}/to.db" "${tmp_dir}/to.files" -mindepth 1 -maxdepth 1 \
      -printf '%f\n' | \
      sed 's/-[^-]\+-[^-]\+$//' | \
      grep -xF "${package%-*-*}"
  )
  if [ -n "${errors}" ]; then
    >&2 printf 'The target repository "%s" already contains the following packages - "repo-remove" them first:\n' \
      "${to_repo}"
    >&2 printf '%s\n' "${errors}"
    exit 2
  fi
  for archive in 'db' 'files'; do
    if [ ! -d "${tmp_dir}/from.${archive}/${package}" ]; then
      >&2 printf 'Repository "%s" does not contain package "%s"\n' \
        "${from_repo}" "${package}"
      exit 2
    fi
    mv "${tmp_dir}/from.${archive}/${package}" "${tmp_dir}/to.${archive}/"
  done
done

# pack the database
for archive in 'db' 'files'; do
  repo_db="${to_repo}"
  if [ "${archive}" = 'files' ]; then
    repo_db="${repo_db%.db.tar.gz}.files.tar.gz"
  fi
  bsdtar -C "${tmp_dir}" -czf "${tmp_dir}/${repo_db##*/}" --strip-components=1 "to.${archive}"
done

# move the database in place
for archive in 'db' 'files'; do
  repo_db="${to_repo}"
  if [ "${archive}" = 'files' ]; then
    repo_db="${repo_db%.db.tar.gz}.files.tar.gz"
  fi
  mv "${tmp_dir}/${repo_db##*/}" "${repo_db}"
done