mirror of
				https://github.com/flatcar/scripts.git
				synced 2025-10-31 08:11:03 +01:00 
			
		
		
		
	eclass is a file, as opposed to the package, which is a directory. So doing `git -C eclass/foo.eclass log -- .` will fail because we can't do "cd eclass/foo.eclass", which is what `-C` is trying to do.
		
			
				
	
	
		
			317 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			317 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| 
 | |
| ##
 | |
| ## Used for syncing with gentoo. Needs to be called from the
 | |
| ## toplevel-directory of portage-stable. If syncing everything or
 | |
| ## syncing metadata/glsa specifically, it is expected that the Gentoo
 | |
| ## repo will have the GLSA files stored in metadata/glsa too.
 | |
| ##
 | |
| ## Parameters:
 | |
| ## -h: this help
 | |
| ## -b: be brief, print only names of changed entries and errors
 | |
| ## -s: skip adding source git commit hash information to commits
 | |
| ##
 | |
| ## Positional:
 | |
| ## 0: Gentoo repository
 | |
| ## #: Entries to update (can be a package name, eclass, category, some special
 | |
| ##    directories like profiles or . for everything)
 | |
| ##
 | |
| ## Example invocations:
 | |
| ##
 | |
| ## sync_with_gentoo -h
 | |
| ##
 | |
| ##   Print a help message.
 | |
| ##
 | |
| ## sync_with_gentoo dev-libs/nettle app-crypt/argon2
 | |
| ##
 | |
| ##   This will update the packages, each in a separate commit. The
 | |
| ##   commit message will contain the commit hash from gentoo repo.
 | |
| ##
 | |
| ## sync_with_gentoo dev-libs
 | |
| ##
 | |
| ##   This will update all the packages in dev-libs category. The
 | |
| ##   commit message will contain the commit hash from gentoo repo.
 | |
| ##
 | |
| 
 | |
| set -euo pipefail
 | |
| 
 | |
| source "$(dirname "${BASH_SOURCE[0]}")/util.sh"
 | |
| 
 | |
| BRIEF=
 | |
| SKIP_GIT_INFO=
 | |
| 
 | |
| while true; do
 | |
|     case ${1-} in
 | |
|         -h)
 | |
|             print_help
 | |
|             exit 0
 | |
|             ;;
 | |
|         -b)
 | |
|             BRIEF=x
 | |
|             shift
 | |
|             ;;
 | |
|         -s)
 | |
|             SKIP_GIT_INFO=x
 | |
|             shift
 | |
|             ;;
 | |
|         --)
 | |
|             shift
 | |
|             break
 | |
|             ;;
 | |
|         -*)
 | |
|             fail "unknown flag '${1}'"
 | |
|             ;;
 | |
|         *)
 | |
|             break
 | |
|             ;;
 | |
|     esac
 | |
| done
 | |
| 
 | |
| if [[ $# -lt 2 ]]; then
 | |
|     fail 'expected at least two positional parameters: a Gentoo repository and at least one package, use -h to print help'
 | |
| fi
 | |
| 
 | |
| if [[ ! -e 'profiles/repo_name' ]]; then
 | |
|     fail 'sync is only possible from ebuild packages top-level directory (a directory from which "./profiles/repo_name" is accessible)'
 | |
| fi
 | |
| 
 | |
| function vcall() {
 | |
|     if [[ -z ${BRIEF} ]]; then
 | |
|         "${@}"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function bcall() {
 | |
|     if [[ -n ${BRIEF} ]]; then
 | |
|         "${@}"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| GENTOO=$(realpath "${1}"); shift
 | |
| # rest are package names
 | |
| 
 | |
| if [[ $(realpath '.') = "${GENTOO}" ]]; then
 | |
|     fail 'trying to sync within a Gentoo repo?'
 | |
| fi
 | |
| 
 | |
| if [[ -z ${SKIP_GIT_INFO} ]] && [[ ! -e ${GENTOO}/.git ]]; then
 | |
|     info "Skipping adding source git commit hash information to commits, ${GENTOO@Q} is not a git repository"
 | |
|     SKIP_GIT_INFO=x
 | |
| fi
 | |
| 
 | |
| glsa_repo=${GENTOO}/metadata/glsa
 | |
| if [[ -z ${SKIP_GIT_INFO} ]] && [[ -e ${glsa_repo} ]] && [[ ! -e ${glsa_repo}/.git ]] && [[ $(git -C "${GENTOO}" status --porcelain -- metadata/glsa) = '?? metadata/glsa' ]]; then
 | |
|     info "Skipping adding source git commit hash information to commits, ${glsa_repo@Q} exists, but it is not a git repository and is not a part of Gentoo git repository"
 | |
|     SKIP_GIT_INFO=x
 | |
| fi
 | |
| unset glsa_repo
 | |
| 
 | |
| # Synchronizes given path with its Gentoo counterpart. Returns true if
 | |
| # there were changes.
 | |
| #
 | |
| # Params:
 | |
| #
 | |
| # 1 - path within ebuild repo
 | |
| function sync_git_prepare() {
 | |
|     local path
 | |
|     path=${1}; shift
 | |
| 
 | |
|     local gentoo_path
 | |
|     gentoo_path="${GENTOO}/${path}"
 | |
| 
 | |
|     if [[ ! -e "${gentoo_path}" ]]; then
 | |
|         info "no ${path@Q} in Gentoo repository"
 | |
|         if [[ ${path} = 'metadata/glsa' ]]; then
 | |
|             info "did you forget to clone https://gitweb.gentoo.org/data/glsa.git/ into ${gentoo_path@Q}?"
 | |
|         fi
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     local -a rsync_opts=( --archive --delete-before )
 | |
| 
 | |
|     case ${path} in
 | |
|         profiles)
 | |
|             rsync_opts+=( --exclude /profiles/repo_name )
 | |
|             ;;
 | |
|     esac
 | |
| 
 | |
|     local parent
 | |
|     dirname_out "${path}" parent
 | |
|     mkdir --parents "${parent}"
 | |
|     rsync "${rsync_opts[@]}" "${gentoo_path}" "${parent}"
 | |
|     if [[ -n $(git status --porcelain -- "${path}") ]]; then
 | |
|         bcall info "updated ${path}"
 | |
|         git add "${path}"
 | |
|         return 0
 | |
|     fi
 | |
|     return 1
 | |
| }
 | |
| 
 | |
| # Creates a git commit. If checking Gentoo commit ID is enabled the
 | |
| # given path is used to get the ID of the commit with the last change
 | |
| # in the path. Name parameter is used for denoting which part has
 | |
| # changed, and sync parameter to denote if the commit is about adding
 | |
| # new package or updating an existing one.
 | |
| #
 | |
| # Params:
 | |
| #
 | |
| # 1 - path
 | |
| # 2 - name
 | |
| # 3 - not empty if existing package was updated, or an empty string if
 | |
| #     the package is new
 | |
| function commit_with_gentoo_sha() {
 | |
|     local path name sync
 | |
|     path=${1}; shift
 | |
|     name=${1}; shift
 | |
|     sync=${1:-}; shift
 | |
| 
 | |
|     local -a commit_extra=()
 | |
|     if [[ -z ${SKIP_GIT_INFO} ]]; then
 | |
|         local commit
 | |
| 
 | |
|         commit=$(git -C "${GENTOO}" log --pretty=oneline -1 -- "${path}" | cut -f1 -d' ')
 | |
|         commit_extra+=( --message "It's from Gentoo commit ${commit}." )
 | |
|         unset commit
 | |
|     fi
 | |
|     commit_msg="${name}: Add from Gentoo"
 | |
|     if [[ -n "${sync}" ]]; then
 | |
|         commit_msg="${name}: Sync with Gentoo"
 | |
|     fi
 | |
|     git commit --quiet --message "${commit_msg}" "${commit_extra[@]}"
 | |
|     GIT_PAGER='cat' vcall git show --stat
 | |
| }
 | |
| 
 | |
| # Simple path sync and commit; takes the contents from Gentoo at the
 | |
| # given path and puts it in the repo.
 | |
| #
 | |
| # 1 - path to sync
 | |
| # 2 - name for commit message
 | |
| function path_sync() {
 | |
|     local path name
 | |
|     path=${1}; shift
 | |
|     name=${1}; shift
 | |
| 
 | |
|     local sync
 | |
|     sync=''
 | |
|     if [[ -e "${path}" ]]; then
 | |
|         sync='x'
 | |
|     fi
 | |
| 
 | |
|     if sync_git_prepare "${path}"; then
 | |
|         commit_with_gentoo_sha "${path}" "${name}" "${sync}"
 | |
|     else
 | |
|         vcall info "no changes in ${path}"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # Goes over the given directory and syncs its subdirectories or
 | |
| # files. No commit is created.
 | |
| function prepare_dir() {
 | |
|     local dir
 | |
|     dir=${1}; shift
 | |
| 
 | |
|     local pkg mod=''
 | |
|     for pkg in "${dir}/"*; do
 | |
|         if sync_git_prepare "${pkg}"; then
 | |
|             mod=x
 | |
|         fi
 | |
|     done
 | |
|     if [[ -n ${mod} ]]; then
 | |
|         return 0
 | |
|     fi
 | |
|     return 1
 | |
| }
 | |
| 
 | |
| # Synces entire category of packages and creates a commit. Note that
 | |
| # if the category already exists, no new packages will be added.
 | |
| #
 | |
| # Params:
 | |
| #
 | |
| # 1 - path to the category directory
 | |
| function category_sync() {
 | |
|     local path
 | |
|     path=${1}; shift
 | |
| 
 | |
|     if [[ ! -e "${path}" ]]; then
 | |
|         if sync_git_prepare "${path}"; then
 | |
|             commit_with_gentoo_sha "${path}" "${path}"
 | |
|         fi
 | |
|     else
 | |
|         if prepare_dir "${path}"; then
 | |
|             commit_with_gentoo_sha "${path}" "${path}" 'x'
 | |
|         fi
 | |
|     fi
 | |
| 
 | |
| }
 | |
| 
 | |
| # Synces entire repo. No new packages will be added.
 | |
| function everything_sync() {
 | |
|     local path mod
 | |
| 
 | |
|     for path in *; do
 | |
|         case ${path} in
 | |
|             licenses|profiles|scripts)
 | |
|                 if sync_git_prepare "${path}"; then
 | |
|                     mod=x
 | |
|                 fi
 | |
|                 ;;
 | |
|             metadata)
 | |
|                 # do only metadata updates
 | |
|                 if sync_git_prepare metadata/glsa; then
 | |
|                     mod=x
 | |
|                 fi
 | |
|                 ;;
 | |
|             eclass|virtual|*-*)
 | |
|                 if prepare_dir "${path}"; then
 | |
|                     mod=x
 | |
|                 fi
 | |
|                 ;;
 | |
|             changelog|*.md)
 | |
|                 # ignore those
 | |
|                 :
 | |
|                 ;;
 | |
|             *)
 | |
|                 info "Unknown entry ${path@Q}, ignoring"
 | |
|                 ;;
 | |
|         esac
 | |
|     done
 | |
|     if [[ -n ${mod} ]]; then
 | |
|         commit_with_gentoo_sha '.' '*' 'x'
 | |
|     fi
 | |
| }
 | |
| 
 | |
| shopt -s extglob
 | |
| 
 | |
| for cpn; do
 | |
|     cpn=${cpn%%*(/)}
 | |
|     case ${cpn} in
 | |
|         .)
 | |
|             everything_sync
 | |
|             ;;
 | |
|         licenses|profiles|scripts)
 | |
|             path_sync "${cpn}" "${cpn}"
 | |
|             ;;
 | |
|         eclass/*.eclass)
 | |
|             path_sync "${cpn}" "${cpn%.eclass}"
 | |
|             ;;
 | |
|         metadata/glsa)
 | |
|             path_sync "${cpn}" "${cpn}"
 | |
|             ;;
 | |
|         metadata)
 | |
|             fail "metadata directory can't be synced, did you mean metadata/glsa?"
 | |
|             ;;
 | |
|         virtual/*/*|*-*/*/*)
 | |
|             fail "invalid thing to sync: ${cpn}"
 | |
|             ;;
 | |
|         virtual/*|*-*/*)
 | |
|             path_sync "${cpn}" "${cpn}"
 | |
|             ;;
 | |
|         eclass|virtual|*-*)
 | |
|             category_sync "${cpn}"
 | |
|             ;;
 | |
|         *)
 | |
|             fail "invalid thing to sync: ${cpn}"
 | |
|             ;;
 | |
|     esac
 | |
| done
 |