jenkins-pipelines/scripts/lib/publish_utils.sh
Davlet Panech 0a297aae9d build.conf: new parameter ARCHIVE_BIG_DIRS
New configuration ARCHIVE_BIG_DIRS to hardlink, copy or symlink the
bigger directories, "mirrors", "aptly" and "docker", when archiving
them to /localdisk/loadbuild.

This option can take on these values:

* checksum-hardlink (default): hardlink files with identical files
  from previous builds' archive directories. Look for StxChecksums
  files in older builds' directories to determine whether the files
  are identical.
* checksum-copy: really copy the files
* top-symlink: create a top-level symlink, such as
  $BUILD_OUTPUT_HOME/mirrors that points to $BUILD_HOME/mirrors

This option also accepts a space-separated list of "dir:method"
pairs, eg:

  checksum-hardlink mirrors:top-symlink

means "use the hardlink method by default, but for mirros/ use the
top-symlink method". The last specification in the list takes
precedence in case of multiple matches.

The default behavior, when this option is empty or missing in
build.conf, is "checksum-hardlink".

New script: helpers/archive-dir.sh, executed as root within a docker
container during the build.

TESTS
=====================================

* Call "archive-misc.sh" manually in various ways and check the output

* Jenkins build + ARCHIVE_BIG_DIRS="checksum-hardlink"
  - Run a full build and make sure most files are copied, but the
    files common between mirrors and aptly (4rd-party DEBs) are
    hardlinked
  - Run a second build and make sure all files are hardlinked
  - Add a dummy change to "build-info", rebuild it, then make sure
    that package is copied, but all other files are hardlinked

* Jenkins build + ARCHIVE_BIG_DIRS commented out
  - Make sure Jenkins creates the hardlinks

Story: 2010226
Task: 47860

Signed-off-by: Davlet Panech <davlet.panech@windriver.com>
Change-Id: I604f840007b79461b5a48dcc4c21fc6316de9a52
2023-04-24 14:24:45 -04:00

134 lines
4.1 KiB
Bash

# bash
#
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
CHECKSUMS_FILENAME="StxChecksums"
create_checksum_files_meta () {
local published_checksum_files_list_file="$1"
local meta_file="${published_checksum_files_list_file}.meta"
if [ -f "$meta_file" ]; then
\rm -f "$meta_file"
fi
cat "$published_checksum_files_list_file" | xargs grep -H -v '^$' > $meta_file
}
publish_file() {
local filename="$1"
local dst_dir="$2"
local published_checksum_files_list_file="$3"
mkdir -p "$dst_dir" || exit 1
local basename
basename="${filename##*/}"
local dst_file
dst_file="$dst_dir/$basename"
local checksum
checksum=$(sha256sum "$filename" | awk '{print $1}' ; check_pipe_status) || exit 1
local p
p=$(nproc)
# find an existing file in $combined_checksums_file that we can
# hardlink to
local link_created
link_created=$(
( if [ -f ${published_checksum_files_list_file}.meta ];
then
grep ":$checksum " ${published_checksum_files_list_file}.meta | cut -d ':' -f 1
else
cat "$published_checksum_files_list_file" | xargs -P $p \grep -l "^$checksum "
fi ) | {
while read checksum_file ; do
local checksum_dir
checksum_dir="${checksum_file%/*}"
link_created=$(
\grep "^$checksum " "$checksum_file" \
| while read x_checksum x_basename x_size x_mtime x_device x_inode x_path ; do
x_filename="$checksum_dir/$x_basename"
if [[ ! -f "$x_filename" || -z "$x_basename" || -z "$x_size" || -z "$x_mtime" || -z "$x_device" || -z "$x_inode" || -z "$x_path" ]] ; then
continue
fi
x_recheck_stat=$(stat --printf '%s %Y %d %i' "$x_filename") || continue
#echo ">>> $x_recheck_stat $x_size $x_mtime $x_device $x_inode" >&2
[[ "$x_recheck_stat" == "$x_size $x_mtime $x_device $x_inode" ]] || continue
# try to link it
if \ln -f "$x_filename" "$dst_file" 2>&1 ; then
echo "LINK $dst_file" >&2
echo "link_created"
fi
cat >/dev/null # read and discard remaining lines to avoid SIGPIPE
exit 0
done
) || exit 1
if [[ "$link_created" == "link_created" ]] ; then
echo "link_created"
cat >/dev/null # read and discard remaining lines to avoid SIGPIPE
exit 0
fi
done
}
[ $? -eq 0 ] || exit 1
)
check_pipe_status || exit 1
# try to link source file to destination
if [[ "$link_created" != "link_created" ]] ; then
link_created=$(
if \ln -f "$filename" "$dst_file" 2>&1 ; then
echo "LINK $dst_file" >&2
echo "link_created"
fi
) || exit 1
fi
# if all else fails, copy it
if [[ "$link_created" != "link_created" ]] ; then
\cp -f --preserve=mode,timestamps "$filename" "$dst_file" || exit 1
echo "COPY $dst_file" >&2
fi
# output published file info + source path
local -a stat
local size device inode mtime
stat=($(stat --printf '%s %Y %d %i' "$dst_file")) || exit 1
size="${stat[0]}"
mtime="${stat[1]}"
device="${stat[2]}"
inode="${stat[3]}"
echo "$checksum $basename $size $mtime $device $inode $filename"
}
find_publish_dirs() {
find "$PUBLISH_ROOT" -mindepth 1 -maxdepth 1 \
-type d \
-name '[0-9][0-9][0-9][0-9]*'
}
find_checksum_files() {
local dir subdir
find_publish_dirs | while read dir ; do
for subdir in "$@" ; do
if [[ -d "$dir/$subdir" ]] ; then
find "$dir/$subdir" -type f -name "$CHECKSUMS_FILENAME"
fi
done
done
check_pipe_status || exit 1
}