> Jose Isaias Cabrera via Cygwin writes:
> > I have a new Win11 PC, and I wanted to capture the same Cygwin setup
> > that I have in another Win10 PC. I copied the C:\cygwin64 folder from
> > the Win10 pc to the Win11 pc,

I use the attached script (rename it to remove the .txt extension) to
clone my cygwin installation.

You can use the generated script to
1. perform a clean reinstall with the same set of packages as a
current  instance.
2. clone an existing install to another instance on this or another machine.

USE AT YOUR OWN RISK.

You must change the variables in the configuration section to your requirements.

You can also edit the generated script, which is created in the same
folder as the cygwin setup executable.


HTH
Doug
-- 
Doug Henderson, Calgary, Alberta, Canada - from gmail.com
#!/usr/bin/bash -e
# djh-reinstall.sh
# created by Doug Henderson
# inspired by similar code posted on stackoverflow and the cygwin mailing list
# updated 2020-05-26 by Doug Henderson
# updated 2023-11-23 by Doug Henderson

# *** USE AT YOUR OWN RISK ***

# djh-reinstall.sh determines a minimal set of packages which will reinstall
# an existing cygwin instance.
#
# You can use the generated script to
# 1. perform clean reinstall with the same set of packages as a current
#    instance.
# 2. clone an existing install to another instance on this or another
#    machine.
#
# It uses the cygcheck-dep script from the cygcheck-dep package to
# determine a set of packages which have no dependent packages.
# It relies on cygwin setup to compute all dependencies.
# You must change the variables in the configuration section to your 
requirements.


arch=$( uname -m)
if [ $arch = "x86"    ] ; then
        bits=32
elif [ $arch = "x86_64" ] ; then
        bits=64
else
        echo "Failed to determine bits for $arch"
        exit 1
fi

################################
# start of configuration section
# You must change the variables in this section to your requirements.

# SETUP_DIR contains the Cygwin setup executable
# This where you saved the installer from https://www/cygwin.com
SETUP_DIR_W="D:\\Users\\Doug\\Down_Loads\\cygwin"

# ROOT is the windows directory which will be the cygwin root directory.
# All of cygwin is installed below this directory.
# Select the 1st following line to install to same dir.
# select the  2nd following line for the recommended root directory.
# I recommend C:\cygwin32 and C:\cygwin64 for 32 bit and 64 bit installs.
# ROOT_W="$( cygpath -wa / )"
  ROOT_W="C:\\cygwin${bits}"

# CACHE is the windows directory containing the local package cache
# You can use one directory, or one for each architecture.
# It is strongly recommended that you use one for each architecture.
# This folder must not be under the ROOT folder.
  CACHE_W="D:\\Users\\Doug\\Down_Loads\\cygwin${bits}cache"

# MIRROR is the URL of a Cygwin mirror site. Pick your favourite, or fastest.
# Use the same one as you select when running the installer: setup_*.exe
  MIRROR="http://mirrors.kernel.org/sourceware/cygwin/";

# end of configuration section
##############################

# remove scatch files
rm -f /tmp/djh-check.*

USAGE="Usage: $0 [--incomplete | -I] [--long | -L] [--overlay DIR | -O DIR] 
[--pause | -P]
        --incomplete, -I      - reinstall incomplete packages only
        --long, -L            - use setup's long instead of short form options
        --overlay DIR, -O DIR - use DIR as an overlay package server
        --pause, -P           - add a pause at end of command script
        --verbose, -v         - verbose, show some extra info
        --debug, -D           - debug, show lots of extra info
        --help, -h            - display usage message and exit

        WARNING: reinstalling incomplete python packages will downgrade
        those python packages that were upgraded by using 'pip install -U PKG'.
"

INCOMPLETE=
LONG=
OVERLAY=
PAUSE=
VERBOSE=
VERSION=
DEBUG=

die() { echo "$*" >&2 ; exit 2 ; }  # complain to STDERR and exit with error
needs_arg() { if [ -z "$OPTARG" ] ; then die "No arg for --$OPT option" ; fi ; }

while getopts "hvDILO:PV-:" OPT ; do
        # echo "*1st: OPT=$OPT OPTIND=$OPTIND NAME=$NAME OPTARG=$OPTARG"
        if [ "$OPT" = "-" ]; then     # long option: reformulate OPT and OPTARG
                OPT="${OPTARG%%=*}"       # extract long option name
                OPTARG="${OPTARG#$OPT}"   # extract long option argument (may 
be empty)
                OPTARG="${OPTARG#=}"      # if long option argument, remove 
assigning `=`
                # echo "*2nd: OPT=$OPT OPTIND=$OPTIND NAME=$NAME OPTARG=$OPTARG"
        fi
        case $OPT in
        h | help )                      echo "$USAGE" ; exit 0 ;;
        v | verbose )           VERBOSE=true ;;
        D | debug )                     DEBUG=true ;;
        I | incomplete )        INCOMPLETE=true ;;
        L | long )                      LONG=true ;;
        O | overlay )           needs_arg; OVERLAY=$OPTARG ;;
        P | pause )                     PAUSE=true ;;
        V | version )           VERSION=true ;;
        ??* )                           die "Illegal option --$OPT" ;;  # bad 
long option
        \?)                                     exit 2 ;;  # bad short option 
(error reported via getopts)
        *)
                echo "*WTF: OPT=$OPT OPTIND=$OPTIND NAME=$NAME OPTARG=$OPTARG"
                exit 1
                ;;
        esac
done
shift $((OPTIND-1)) # remove parsed options and args from $@ list

if [ -n "$DEBUG" ] ; then
        echo "Options: INCOMPLETE=$INCOMPLETE LONG=$LONG OVERLAY=$OVERLAY"
        echo "         PAUSE=$PAUSE VERBOSE=$VERBOSE DEBUG=$DEBUG"
        echo ""
fi

# precompute some variables

# SETUP_EXE is the architecture dependent Cygwin setup executable.
SETUP_EXE="setup-$(arch).exe"

# SETUP_PATH_W is the full windows path to the Cygwin setup executable.
SETUP_PATH_W="${SETUP_DIR_W}\\${SETUP_EXE}"

# CMD_W is the full windows path to the reinstall command we are creating.
CMD_W="${SETUP_DIR_W}\\djh-reinstall${bits}.cmd"

# CMD_U is the full cygwin path to the reinstall command we are creating.
CMD_U="$( cygpath -u ${CMD_W} )"

# show the configuration variables
show_vars() {
        EFMT="INFO: %-14s = %-60s # %s\n"
        printf "${EFMT}"  SETUP_DIR_W  ${SETUP_DIR_W}  "windows dir containing 
setup exe"
        printf "${EFMT}"  ROOT_W       ${ROOT_W}       "windows path of cygwin 
root"
        printf "${EFMT}"  CACHE_W      ${CACHE_W}      "setup exe cache 
directory"
        printf "${EFMT}"  MIRROR       ${MIRROR}       "URL of preferred mirror"

        if true ; then
                echo ""
                printf "${EFMT}"  reinstall.sh  ${0}             "this script"
                printf "${EFMT}"  arch          ${arch}          "architecture 
name X86 or X86_64"
                printf "${EFMT}"  bits          ${bits}          "architecture 
bits 32 or 64"
                printf "${EFMT}"  SETUP_EXE     ${SETUP_EXE}     "setup 
executable name"
                printf "${EFMT}"  SETUP_PATH_W  ${SETUP_PATH_W}  "windows path 
to setup executable"
                printf "${EFMT}"  CMD_W         ${CMD_W}         "windows path 
to output cmd script"
                printf "${EFMT}"  CMD_U         ${CMD_U}         "unix path to 
output cmd script"
        fi
}
if [ -n "$VERBOSE" ] || [ -n "$DEBUG" ] ; then
        show_vars
fi

# check that required programs are installed
check_dep() {
        if [ ! -x $( which $1 > /dev/null 2>&1 ) ] ; then
                echo >&2 "$1 : command not found"
                pkg=$( cygcheck -f /usr/bin/$1 )
                echo >&2 "Please install $pkg which provides $1"
                exit 1
        fi
}
check_dep cygcheck-dep
check_dep unix2dos.exe

if [ ! -f $( cygpath -u "${SETUP_PATH_W}" ) ] ; then
        echo >&2 "WARNING: setup not found: $( cygpath -u ${SETUP_PATH_W} )"
        echo >&2 "WARNING: ${SETUP_EXE} must be installed to run the generated 
script"
fi

FMT="INFO: %-24s shows %4d packages\n"
if [ -n "$INCOMPLETE" ] ; then
        echo "WARNING: This resets all Python packages upgraded using 'pip 
install -U PKG'."

        cygcheck -c | grep -a "Incomplete" >> /tmp/djh-check.p2.log

        # our sed script does:
        # remove everything after the first space to end of line.
        # delete line(s) starting with '_' (just in case).
        sed     < /tmp/djh-check.p2.log \
                -e 's/ .*$//' \
                -e '/^_/d' \
                > /tmp/djh-check.p2a.log

        p2=( $( sort --unique /tmp/djh-check.p2a.log ) )
        printf "${FMT}" "cgcheck -c Incomp" ${#p2[*]}
else
        # p1 is the list of all installed packages
        # p2 is the list of "leaf" packages
        # p3 is the list of packages recursively required by "leaf" packages

        echo 
"========================================================================"
        echo "(This may take a minute or so)"
        echo "# generated at $( date --rfc-3339=sec )" > /tmp/djh-check.p1.log
        cygcheck -c >> /tmp/djh-check.p1.log

        # our sed script does:
        # delete first 2 lines.
        # remove everything after the first space to end of line.
        # delete line(s) starting with '_'.
        sed     < /tmp/djh-check.p1.log \
                -e '1,2d' \
                -e 's/ .*$//' \
                -e '/^_/d' \
                > /tmp/djh-check.p1a.log
        p1=( $( sort --unique /tmp/djh-check.p1a.log ) )
        printf "${FMT}" "cgcheck -c" ${#p1[*]}
        ( echo "p1 =" ; echo "    ${p1[*]}" ) > /tmp/djh-check.p1b.log

        echo 
"========================================================================"
        echo "(This may take a minute or so)"
        echo "# generated at $( date --rfc-3339=sec )" > 
/tmp/djh-check.dep-pp2.log
        ( cygcheck-dep -c -l -I 2> /dev/null || true ) >> 
/tmp/djh-check.dep-pp2.log

        # our sed script does:
        # delete lines starting with '/', \s+, ' _'.
        # remove open and closing parenthesis.
        # strip leading spaces.
        # strip trailing spaces.
        # replace multiple spaces with a single space.
        # delete empty lines.
        # replace spaces with newlines.
        sed     < /tmp/djh-check.dep-pp2.log \
                -e '/^\//d' \
                -e '/^\#/d' \
                -e '/^ _/d' \
                -e '/^ ( /s/[()]//g' \
                -e 's/\[Base\]//g' \
                -e 's/^  *//' \
                -e 's/  *$//' \
                -e 's/  */ /' \
                -e '/^$/d' \
                -e 's/ /\n/g' \
                > /tmp/djh-check.dep-pp2a.log
        p2=( $( sort --unique /tmp/djh-check.dep-pp2a.log ) )
        printf "${FMT}" "cygcheck-dep -c -l -I" ${#p2[*]}
        ( echo "p2 =" ; echo "    ${p2[*]}" ) > /tmp/djh-check.dep-pp2b.log

        echo 
"========================================================================"
        echo "(This may take a minute or so)"
        echo "# generated at $( date --rfc-3339=sec )" > 
/tmp/djh-check.dep-pp3.log
        ( cygcheck-dep -c -R ${p2[*]} 2> /dev/null || true ) >> 
/tmp/djh-check.dep-pp3.log

        # our sed script does:
        # delete lines starting with '_'.
        # remove 'recursively requires ' comments.
        # remove ')'.
        # strip leading spaces.
        # strip trailing spaces.
        # replace multiple spaces with a single space.
        # delete empty lines.
        # replace spaces with newlines.
        sed     < /tmp/djh-check.dep-pp3.log \
                -e '/^\#/d' \
                -e '/^_/d' \
                -e 's/: recursively requires ( */ /' \
                -e 's/ *) *$//' \
                -e 's/^ *//' \
                -e 's/  *$//' \
                -e '/^$/d' \
                -e 's/ /\n/g' \
                > /tmp/djh-check.dep-pp3a.log
        p3=( $( sort --unique /tmp/djh-check.dep-pp3a.log ) )
        printf "${FMT}" "cygcheck-dep -c -R" ${#p3[*]}
        ( echo "p3 =" ; echo "    ${p3[*]}" ) > /tmp/djh-check.dep-pp3b.log
fi

echo "========================================================================"
# create the djh-reinstall command script.

if [ -z $LONG ] ; then
        # use short options to save space
        opt_delete_orphans=-o
        opt_local_package_dir=-l
        opt_no_desktop=-d
        opt_no_shortcuts=-n
        opt_no_verify=-X
        opt_only_site=-O
        opt_packages=-P
        opt_pubkey=-K
        opt_quiet=-q
        opt_root=-R
        opt_site=-s
        opt_upgrade_also=-g
else
        # use long options for readability
        opt_delete_orphans=--delete-orphans
        opt_local_package_dir=--local-package-dir
        opt_no_desktop=--no-desktop
        opt_no_shortcuts=--no-shortcuts
        opt_no_verify=--no-verify
        opt_only_site=--only-site
        opt_packages=--packages
        opt_pubkey=--pubkey
        opt_quiet=--quiet-mode
        opt_root=--root
        opt_site=--site
        opt_upgrade_also=--upgrade-also
fi

# echo    "DEBUG: \$CMD_U = $CMD_U"
rm -f   ${CMD_U}
touch   ${CMD_U}

cat     >> ${CMD_U} <<EOF
@echo off
@rem This file is $CMD_W
@rem It was generated
@rem   by    ${USER}@${HOSTNAME}
@rem   at    $( date --rfc-3339=sec )
@rem   using $( cygpath -au $0 )
@rem   AKA   $( cygpath -aw $0 )
@rem
@rem WARNING: Changes will be overwritten without warning.
@rem
@SETLOCAL
@SETLOCAL ENABLEEXTENSIONS
${SETUP_PATH_W} ^
 $opt_quiet $opt_no_desktop $opt_no_shortcuts ^
 $opt_delete_orphans $opt_upgrade_also $opt_only_site ^
 $opt_root "${ROOT_W}" ^
 $opt_local_package_dir "${CACHE_W}" ^
$( if [ -n "$OVERLAY" ]; then echo " $opt_no_verify $opt_site $OVERLAY ^\n" ; 
fi; )\
 $opt_site ${MIRROR} ^
 $opt_packages ${p2[*]}
$( if [ -n "$PAUSE" ]; then echo "@pause" ; else echo "@rem" ; fi )
EOF
# sed -i -e 's/  / /g' ${CMD_U}

echo "INFO: cmd line length (max=~8192): $( wc --max-line-length < ${CMD_U} )"
echo "INFO: when the line length exceeds the max, you must edit \"${CMD_W}\""
echo ""

# display the command script without non-echoed lines (optional)
# sed < ${CMD_U} -e '/^\@/d'

# Convert the command script from unix to dos line endings
unix2dos -ascii --keepdate --quiet --oldfile ${CMD_U}

# remove scatch files
if [ -z "$DEBUG" ] ; then
        rm -f /tmp/djh-check.*
fi

# -30-
-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to