From patchwork Thu Mar 4 11:55:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denton Liu X-Patchwork-Id: 1881 Return-Path: Delivered-To: patchwork@archlinux.org Received: from mail.archlinux.org [95.216.189.61] by patchwork.archlinux.org with IMAP (fetchmail-6.4.16) for (single-drop); Thu, 04 Mar 2021 11:56:05 +0000 (UTC) Received: from mail.archlinux.org by mail.archlinux.org with LMTP id vShwANXKQGCw8wgAK+/4rw (envelope-from ) for ; Thu, 04 Mar 2021 11:56:05 +0000 Received: from luna.archlinux.org (luna.archlinux.org [IPv6:2a01:4f8:160:3033::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits)) (No client certificate requested) by mail.archlinux.org (Postfix) with ESMTPS id 8CE4D44316F; Thu, 4 Mar 2021 11:56:04 +0000 (UTC) Received: from luna.archlinux.org (luna.archlinux.org [127.0.0.1]) by luna.archlinux.org (Postfix) with ESMTP id 42D192D8B6; Thu, 4 Mar 2021 11:56:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lists.archlinux.org; s=luna; t=1614858964; bh=nGli10jpSDCF1gfMgB3seS2J64NQt8YwNEafzqXrg6s=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc; b=R6dzgAcRHagJgVJ1Wqqg8MG1t7lV/hvKWYTee8T0lqitYNMewuDjMj0YDqSUPZWzR X53H9xUFPYVFT+Az2/9EuNP7DgdpHDG8VWbg2U5rkZKQwFfgfn1OhYf1PEzLgQ2rCK YD+lUQxLJGjfk2HsqeHJ13PttBdz4/IqTN9UY1YnLfOq6S59S0oaU1Zg3CGQTJvi6o y2NBMZPLyy4YW8z/9q19pdVr3YzUtEPVQTuorEvoARYit4FdcWPgrqNV+kWksRtJPi w6vn+/CkWGMDiKKYxW40GX037pdTy+f6YlppPiAhQQ5FnqGOBNMtmnMupczF8Qjxz2 wRo+d/uhF1OgyqBMd9bppPyUo0OrUW9URiQH6ba0vN08OzwT1lUFK+f5F1DoYnnkWn oS1VyK5Huk1EiiAHMjF8EDvtEoWtRYy7GQh3rL+LZcu54UuxgTcb7FFUiSgHIFEvDi yKFkcA3mHMJx+MPohgSHY6mNL6IXv/rpHfrZOoSJzmRzgcT+GZ+Q22caHbYhSPZsJ3 FW8hGPwY+BXv67ZGbvJA20CW9oUyDvh2wruiHR42fHUmEEkYNfOVsDKtsDYD2Vj9W6 WYQX0jkcJd0jgBRcrFz2IKGMUFhD85TS2TbalhGuMWgdgra1a5c4R2l4mNXzPOVJHH Hef76Xp9tFeH1tn8xZ53ZeBU= Received: from luna.archlinux.org (luna.archlinux.org [127.0.0.1]) by luna.archlinux.org (Postfix) with ESMTP id 930952D8B3 for ; Thu, 4 Mar 2021 11:56:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on luna.archlinux.org X-Spam-Level: X-Spam-Status: No, score=0.4 required=5.0 tests=DKIM_SIGNED=0.1, DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,FREEMAIL_FROM=0.5, RCVD_IN_DNSWL_NONE=-0.0001,SPF_HELO_NONE=0.001, T_DMARC_POLICY_NONE=0.01,T_DMARC_SIMPLE_DKIM=0.01 autolearn=no autolearn_force=no version=3.4.4 X-Spam-BL-Results: [127.0.5.0] Received: from mail-pg1-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536]) by luna.archlinux.org (Postfix) with ESMTPS for ; Thu, 4 Mar 2021 11:56:00 +0000 (UTC) Received: by mail-pg1-x536.google.com with SMTP id n10so18744523pgl.10 for ; Thu, 04 Mar 2021 03:56:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/DNnTqyNKXd+A2EiqhlTNAnynJrs7ajJEWaFblAH/9o=; b=jxUnEPXjtQJfSly/Bqx7de3TaXnrHBWB+iKio6kqTRjAnBHrmqhJTQcuKe1hlw60wB uJi6PzbbfUAaycyTtBznGSuVqRSLYS3tx08Ugued/l9gSRSdpZywi4aX+Wl17CmKXo0s o4eNbhf2+pP+N9gZ+azLa4SivzIrLl3nqoF5KsG0fLeGTalMgME0BM99WJrwRxgsMNZg tr7ET7cTybhDJ+rvVn3tyUjoVeNBsmwVJ8PBAO98S/kuqx/oHoPZOGdeV7Fp7BmwQoob oV8e/moKltO+gQJeRTJafDTFGp5ukjVO4byjByE1dVs65iC7i9MtcObMcIBtDWU7TxpM cqqA== X-Gm-Message-State: AOAM531uyk8M021esc4481ixnjNbS5yQfxkx3c9L9xSQRaBWKfJW6oJb qIcy2M1GjorD+izYTO+BGCVHW/whwcA= X-Google-Smtp-Source: ABdhPJwoRn3jTL6xMpVzQyrteCkaKtRqUPMXuJTfpSpu9tFGEz0+X+DexLGQCzWuNQZZ8AST9w+yYg== X-Received: by 2002:a05:6a00:15cc:b029:1ba:5282:3ab8 with SMTP id o12-20020a056a0015ccb02901ba52823ab8mr3526489pfu.77.1614858958200; Thu, 04 Mar 2021 03:55:58 -0800 (PST) Received: from archbookpro.localdomain ([172.92.165.181]) by smtp.gmail.com with ESMTPSA id 188sm27620300pfz.119.2021.03.04.03.55.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Mar 2021 03:55:57 -0800 (PST) To: pacman-contrib@lists.archlinux.org Subject: [PATCH v2 3/3] pacdiff: Learn the (M)erge mode Date: Thu, 4 Mar 2021 03:55:47 -0800 Message-Id: X-Mailer: git-send-email 2.31.0.rc1.228.gb75b4e4ce2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: pacman-contrib@lists.archlinux.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Discussion list for pacman-contrib development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Denton Liu via pacman-contrib From: Denton Liu Reply-To: Discussion list for pacman-contrib development Cc: Denton Liu Errors-To: pacman-contrib-bounces@lists.archlinux.org Sender: "pacman-contrib" Authentication-Results: mail.archlinux.org; dkim=pass header.d=lists.archlinux.org header.s=luna header.b=R6dzgAcR; dmarc=pass (policy=none) header.from=archlinux.org; spf=pass (mail.archlinux.org: domain of pacman-contrib-bounces@lists.archlinux.org designates 2a01:4f8:160:3033::2 as permitted sender) smtp.mailfrom=pacman-contrib-bounces@lists.archlinux.org X-Rspamd-Queue-Id: 8CE4D44316F X-Spamd-Result: default: False [2.79 / 15.00]; HAS_REPLYTO(0.00)[pacman-contrib@lists.archlinux.org]; RCVD_VIA_SMTP_AUTH(0.00)[]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(-0.20)[+ip6:2a01:4f8:160:3033::2:c]; R_MISSING_CHARSET(2.50)[]; REPLYTO_ADDR_EQ_FROM(0.00)[]; BROKEN_CONTENT_TYPE(1.50)[]; DKIM_TRACE(0.00)[lists.archlinux.org:+]; RCPT_COUNT_TWO(0.00)[2]; DMARC_POLICY_ALLOW(-0.50)[archlinux.org,none]; MAILLIST(-0.20)[mailman]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; ASN(0.00)[asn:24940, ipnet:2a01:4f8::/29, country:DE]; FROM_NEQ_ENVFROM(0.00)[pacman-contrib@lists.archlinux.org,pacman-contrib-bounces@lists.archlinux.org]; ARC_NA(0.00)[]; R_DKIM_ALLOW(-0.20)[lists.archlinux.org:s=luna]; RCVD_COUNT_FIVE(0.00)[6]; FROM_HAS_DN(0.00)[]; TAGGED_RCPT(0.00)[]; PREVIOUSLY_DELIVERED(0.00)[pacman-contrib@lists.archlinux.org]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; NEURAL_HAM(-0.00)[-1.000]; FREEMAIL_CC(0.00)[gmail.com]; FORGED_SENDER_MAILLIST(0.00)[] X-Rspamd-Server: mail.archlinux.org Currently, pacdiff only allows users to diff between the current file and the new file. However, the merging of files could be automated by the use of some 3-way merge utility. Teach pacdiff the (M)erge mode which performs a 3-way merge using a given $MERGEPROG (`diff3 -m` by default). The base file is taken from from the second-newest package in the cache. Signed-off-by: Denton Liu --- doc/pacdiff.8.txt | 9 +++-- src/pacdiff.sh.in | 83 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/doc/pacdiff.8.txt b/doc/pacdiff.8.txt index a89c0e7..592da72 100644 --- a/doc/pacdiff.8.txt +++ b/doc/pacdiff.8.txt @@ -18,8 +18,8 @@ Description ----------- pacdiff is a script which looks for pacorig, pacnew and pacsave files from the backup entries found in the local Pacman db. For every found file the option is -given to view, skip, diff, remove or overwrite the found pacorig, pacnew or -pacsave file. +given to view, merge, skip, diff, remove or overwrite the found pacorig, pacnew +or pacsave file. Environment ----------- @@ -29,6 +29,9 @@ Environment *DIFFSEARCHPATH*:: Override the default search path '/etc', only when using find. +*MERGEPROG*:: + Override the default 'diff3 -m' 3-way merge program. One possible + alternative is 'git merge-file -p'. Options ------- @@ -47,6 +50,8 @@ Options *\--nocolor*:: Remove colors from output. +*-c, \--cachedir *:: + Scan 'dir' instead as the pacman cache for 3-way merge base candidates. See Also -------- diff --git a/src/pacdiff.sh.in b/src/pacdiff.sh.in index a50cb93..fc18023 100644 --- a/src/pacdiff.sh.in +++ b/src/pacdiff.sh.in @@ -27,6 +27,8 @@ LIBRARY=${LIBRARY:-'@libmakepkgdir@'} diffprog=${DIFFPROG:-'vim -d'} diffsearchpath=${DIFFSEARCHPATH:-/etc} +mergeprog=${MERGEPROG:-'diff3 -m'} +cachedir= USE_COLOR='y' declare -a oldsaves declare -i USE_FIND=0 USE_LOCATE=0 USE_PACDB=0 OUTPUTONLY=0 @@ -53,15 +55,18 @@ Search Options: select one (default: --pacmandb) -p/--pacmandb scan active config files from pacman database General Options: - -o/--output print files instead of merging them - --nocolor remove colors from output + -o/--output print files instead of merging them + --nocolor remove colors from output + -c/--cachedir scan "dir" for 3-way merge base candidates. + (default: read from @sysconfdir@/pacman.conf) Environment Variables: DIFFPROG override the merge program: (default: 'vim -d') DIFFSEARCHPATH override the search path. (only when using find) (default: /etc) + MERGEPROG override the 3-way merge program: (default: 'diff3 -m') -Example: DIFFPROG=meld DIFFSEARCHPATH="/boot /etc /usr" $myname +Example: DIFFPROG=meld DIFFSEARCHPATH="/boot /etc /usr" MERGEPROG="git merge-file -p" $myname Example: $myname --output --locate EOF @@ -83,6 +88,62 @@ print_existing_pacsave(){ done } +base_cache_tar() { + package="$1" + + [[ -d $cachedir ]] || + die "cachedir '%s' does not exist or is not a directory" "$cachedir" + + # unlikely that this will fail, but better make sure + pushd "$cachedir" &>/dev/null || die "failed to chdir to '%s'" "$cachedir" + + find "$PWD" -name "$package-[0-9]*.pkg.tar*" | pacsort --files | sed -ne '2p' + + popd &>/dev/null +} + +merge_file() { + pacfile="$1" + file="$2" + + package="$(pacman -Qoq "$file")" || return 1 + base_tar="$(base_cache_tar "$package")" + + if [[ -z $base_tar ]]; then + msg2 "Unable to find a base package." + return 1 + fi + + basename="$(basename "$file")" + base="$(mktemp --tmpdir "$basename.base.XXX")" + merged="$(mktemp --tmpdir "$basename.merged.XXX")" + + tar -xOf "$base_tar" "${file#/}" >"$base" + if $mergeprog "$file" "$base" "$pacfile" >"$merged"; then + msg2 "Merged without conflicts." + fi + + $diffprog "$file" "$merged" + + while :; do + ask "Would you like to use the results of the merge? [y/n] " + + read c || return 1 + case $c in + y|Y) break ;; + n|N) return 1 ;; + *) msg2 "Invalid answer." ;; + esac + done + + if ! cp -v "$merged" "$file"; then + warning "Unable to write merged file to %s. Merged file is preserved at %s" "$file" "$merged" + return 1 + fi + rm -v "$pacfile" "$base" "$merged" + return 0 +} + cmd() { if (( USE_LOCATE )); then locate -0 -e -b \*.pacnew \*.pacorig \*.pacsave '*.pacsave.[0-9]*' @@ -114,6 +175,8 @@ while [[ -n "$1" ]]; do OUTPUTONLY=1;; --nocolor) USE_COLOR='n';; + -c|--cachedir) + cachedir="$2"; shift;; -V|--version) version; exit 0;; -h|--help) @@ -135,6 +198,10 @@ if ! type -p ${diffprog%% *} >/dev/null && (( ! OUTPUTONLY )); then die "Cannot find the $diffprog binary required for viewing differences." fi +if ! type -p ${mergeprog%% *} >/dev/null && (( ! OUTPUTONLY )); then + die "Cannot find the $mergeprog binary required for merging differences." +fi + case $(( USE_FIND + USE_LOCATE + USE_PACDB )) in 0) USE_PACDB=1;; # set the default search option [^1]) error "Only one search option may be used at a time" @@ -153,6 +220,10 @@ if (( USE_PACDB )); then fi fi +if [[ -z $cachedir ]]; then + cachedir="$(pacman-conf CacheDir)" +fi + # see http://mywiki.wooledge.org/BashFAQ/020 while IFS= read -u 3 -r -d '' pacfile; do file="${pacfile%.pac*}" @@ -181,7 +252,7 @@ while IFS= read -u 3 -r -d '' pacfile; do rm -v "$pacfile" else while :; do - ask "(V)iew, (S)kip, (R)emove %s, (O)verwrite with %s, (Q)uit: [v/s/r/o/q] " "$file_type" "$file_type" + ask "(V)iew, (M)erge, (S)kip, (R)emove %s, (O)verwrite with %s, (Q)uit: [v/m/s/r/o/q] " "$file_type" "$file_type" read c || break case $c in q|Q) exit 0;; @@ -194,6 +265,10 @@ while IFS= read -u 3 -r -d '' pacfile; do rm -v "$pacfile" break fi ;; + m|M) + if merge_file "$pacfile" "$file"; then + break + fi ;; s|S) break ;; *) msg2 "Invalid answer." ;; esac