2016-08-20 2 views

Antwort

0

Das folgende Skript dies erreicht, und hat einige Smarts um zu arbeiten patch einen Fehlercode zurückkehrt, wenn einige oder alle einen Patch bereits installiert wurde :

#!/bin/bash 

# Usage: gem-patch 
# Code updates: https://gist.github.com/HaleTom/275f28403828b9b9b93d313990fc94f4 

# Features: 
# Work around `patch` returning non-zero if some patch hunks are already applied 
# Apply all patches in $patch_dir (in order) to their corresponding gem(s) 
# Build a gem only after all patches have been applied 
# Only build the gem if it was patched 
# Robust error handling 

patch_dir="$HOME/lib/gem-patch" 
# Patches are assumed to be made with git patch 
# Files are to be named gem-name or gem-name.patch-explanation 
# Multiple patches are applied in filename order 

set -e -u 
shopt -s nullglob # Globs are '' when no files match a pattern 
gems_dir="$(gem environment gemdir)/gems" 

if ! compgen -G "$patch_dir/*" > /dev/null; then 
    echo "Couldn't find any patches located in $patch_dir. Quitting." 2>&1 
    exit 1 
fi 

# Save the current "gemname-1.2.3" so that when it changes to a new one 
# (ie, all patches have been applied) it can be built only once 
function build_prev_if_needed { 
    if [[ ${prev_gem_ver:="${gem_ver:=''}"} != "$gem_ver" ]]; then 
    # We've moved on to another gem, build the last one 
    (cd "$gems_dir/$prev_gem_ver" && 
     gem build "${prev_gem_ver%%-[-0-9.]*}.gemspec" 
    ) 
    fi 
    prev_gem_ver="$gem_ver" 
} 

for patch in "$patch_dir"/*; do 
    gem_name=$(basename "${patch%%[.]*}") found_one=false 
    # $gem_dir becomes "rails-5.0.0.1" from find at end of loop 
    while read -d '' -r gem_dir; do 
    found_one=true 
    # Build the previously seen gem if we've moved on to a new one 
    gem_ver=${gem_dir##$gems_dir/} 
    echo -n "$gem_ver (patch $(basename "$patch")): " 
    # If we could reverse the patch, then it has already been applied; skip it 
    if patch --dry-run --reverse -d "$gem_dir" -fp1 --ignore-whitespace -i "$patch" >/dev/null 2>&1; then 
     echo "skipping (already applied)" 
     continue 
    else # patch not yet applied 
     echo "patching..." 
     # Patch returns non-zero if some hunks have already been applied 
     if ! patch -d "$gem_dir" -fsp1 --ignore-whitespace -i "$patch"; then 
     # Check that the patch was fully applied by pretending to reverse it 
     if patch --dry-run --reverse -d "$gem_dir" -fp1 --ignore-whitespace -i "$patch" >/dev/null 2>&1; then 
      echo "Ignoring failure: hunk(s) were already applied" 
     else 
      echo "Patch failed for $gem_dir" >&2; exit 1; 
     fi 
     fi 
     build_prev_if_needed 
    fi 
    done < <(find "$gems_dir" -maxdepth 1 -type d -regex ".*/$gem_name-[-0-9.]+" -print0) 
    if [[ $found_one != true ]]; then 
    echo "Fatal: Patch file '$(basename "$patch")': Couldn't find any gem sources named $gems_dir/$(basename "$patch")*" >&2; exit 1 
    fi 
done # $gem_dir is now blank 

gem_ver='' 
build_prev_if_needed 
Verwandte Themen