• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2# Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3# Licensed under the Mulan PSL v2.
4# You can use this software according to the terms and conditions of the Mulan PSL v2.
5# You may obtain a copy of Mulan PSL v2 at:
6#     http://license.coscl.org.cn/MulanPSL2
7# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9# PURPOSE.
10# See the Mulan PSL v2 for more details.
11
12set -e
13
14self=$(basename "$0")
15
16function usage {
17    echo "Usage: $self [overrides_absolute_path] [target_absolute_path]"
18    exit 1
19}
20
21if [ "$#" -ne 2 ]; then
22    usage
23fi
24
25if [[ $1 != /* ]] || [[ $2 != /* ]]; then
26    usage
27fi
28
29overrides=$1
30target=$2
31
32# Overrides is based on mirror structure of $overrides and $target directory.
33# So, for each file and directory **under $overrides**, we have defined following
34# overriding semantics:
35# 1. For a directory, if there is no corresponding directory in $target, the whole
36# directory should exist under $target.
37# 2. For a directory(A), if there is corresponding directory in $target(B), we should
38# override all subdirectories and files, but should not touch files not appear in
39# A but in B.
40# 3. For a file(A), if it is an empty file, it means corresponding file in $target(B)
41# should be deleted. We first backup B, then delete it.
42# 4. For a file(A), if it is not empty, we first backup its corresponding file(B), then
43# override B with content of A.
44#
45# Based on above overridng semantic, this process is implemented with target state-based
46# approach. Besides, for performance and being able to reflect latest changes of libchcore,
47# We use symlink for all override operations. So, consider the target state of a directory
48# and file under $override:
49# 1. For a directory(A), if B exists, then we recurse to check subdirectories and files of A.
50# 2. For a directory(A), if B not exists, then the target state should be that B is a
51# symlink to A.
52# 3. For a file(A), if it is empty, then the target state should be: (1) backup file of B
53# exists, and (2) B is deleted
54# 4. For a file(A), if it is not empty, then the target state should be: (1) backup file of B
55# exists, and (2) B is a symlink to A
56#
57# We recursively iterate over each subdirectories and files under $override, for each of
58# them, check the state of their corresponding B is reached target state or not. If reached,
59# we just skip for idempotence. Otherwise, we perform backup and link operations(if needed).
60
61function traverse {
62    for file in "$1"/*; do
63        rel_path=${file#$overrides/}
64        target_file=$target/$rel_path
65
66        if [ -d "$file" ]; then
67            if [ ! -e "$target_file" ]; then
68                ln -s "$file" "$target_file"
69                echo "--- Overrided ${target_file} with ${file} symlink"
70            elif [ ! -L "$target_file" ]; then
71                traverse "$file"
72            else
73                echo "--- Target directory ${target_file} has been overrided, skipping..."
74            fi
75        elif [ -f "$file" ]; then
76            if [ ! -s "$file" ]; then
77                if [ -e "$target_file" ]; then
78                    mv "$target_file" "$target_file.bak"
79                    echo "--- Overrided ${target_file} with ${file}"
80                else
81                    echo "--- Target file ${target_file} has been deleted, skipping..."
82                fi
83            else
84                if [ ! -e "$target_file" ]; then
85                    ln -s "$file" "$target_file"
86                    echo "--- Overrided ${target_file} with ${file}"
87                elif [ ! -L "$target_file" ]; then
88                    mv "$target_file" "$target_file.bak"
89                    ln -s "$file" "$target_file"
90                    echo "--- Overrided ${target_file} with ${file}"
91                else
92                    echo "--- Target file ${target_file} is already a symlink, skipping..."
93                fi
94            fi
95        fi
96    done
97}
98
99traverse $overrides
100