public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Doug Henderson <djndnbvg@gmail.com>
To: cygwin@cygwin.com
Subject: Re: Capturing a Cygwin instance from another PC
Date: Thu, 23 Nov 2023 13:27:52 -0700	[thread overview]
Message-ID: <CAJ1FpuOdmxGtYXhieiJN3GtbtGKFkMMBt4kfAg98kgS+3Dac6A@mail.gmail.com> (raw)
In-Reply-To: <87o7fkmhy1.fsf@Gerda.invalid>

[-- Attachment #1: Type: text/plain, Size: 807 bytes --]

> 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

[-- Attachment #2: djh-reinstall.sh.txt --]
[-- Type: text/plain, Size: 11732 bytes --]

#!/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-

  reply	other threads:[~2023-11-23 20:28 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-22 14:53 Jose Isaias Cabrera
2023-11-22 15:43 ` Bill Stewart
2023-11-22 16:15   ` Eliot Moss
2023-11-22 21:38     ` Jose Isaias Cabrera
2023-11-22 22:01       ` Ken Brown
2023-11-23  3:25       ` Eliot Moss
2023-11-23  9:12         ` Backwoods BC
2023-11-22 22:44     ` Cedric Blancher
2023-11-23 15:24       ` Corinna Vinschen
2023-11-22 16:20 ` EXTERNAL SENDER: " Dale Lobb (Sys Admin)
2023-11-22 21:49   ` Jose Isaias Cabrera
2023-11-23 18:40 ` ASSI
2023-11-23 20:27   ` Doug Henderson [this message]
2023-11-27  2:36 ` Chris Wagner
2023-11-27  8:24   ` ASSI
2023-11-27 17:43     ` Brian Inglis
2023-11-29 17:42       ` Jose Isaias Cabrera
2024-01-14 19:23       ` Andrey Repin
2023-11-27  2:46 ` Capturing a Cygwin instance from another PC (CORRECTION) Chris Wagner
2023-12-07 22:59 ` Capturing a Cygwin instance from another PC Andrew Schulman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAJ1FpuOdmxGtYXhieiJN3GtbtGKFkMMBt4kfAg98kgS+3Dac6A@mail.gmail.com \
    --to=djndnbvg@gmail.com \
    --cc=cygwin@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).