├── .gitignore ├── README.md ├── docs └── man │ └── man1 │ ├── git-cms-addpkg.1 │ ├── git-cms-checkdeps.1 │ ├── git-cms-checkout-topic.1 │ ├── git-cms-cvs-history.1 │ ├── git-cms-init.1 │ ├── git-cms-merge-topic.1 │ ├── git-cms-rebase-topic.1 │ ├── git-cms-rmpkg.1 │ ├── git-cms-showtags.1 │ └── git-cms-squash-topic.1 ├── git-cms-addpkg ├── git-cms-checkdeps ├── git-cms-checkout-topic ├── git-cms-cherry-pick-pr ├── git-cms-cvs-history ├── git-cms-fetch-pr ├── git-cms-import-tagset ├── git-cms-init ├── git-cms-merge-topic ├── git-cms-rebase-topic ├── git-cms-remote ├── git-cms-rmpkg ├── git-cms-show-pr ├── git-cms-showtags ├── git-cms-sparse-checkout ├── git-cms-squash-topic ├── git-proxy ├── init.sh ├── share └── etc │ └── profile.d │ └── S99cms-git-tools-completion.sh └── tests └── test_wrappers.sh /.gitignore: -------------------------------------------------------------------------------- 1 | test/ 2 | docs/man/man1 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cms-git-tools 2 | ============= 3 | 4 | CMS Git Helpers 5 | 6 | # INSTALL 7 | 8 | These helpers should be part of any release since CMSSW_7_0_0_pre0. If you want 9 | to use them standalone, just clone this repository and add it to your PATH. 10 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-addpkg.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_ADDPKG 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-addpkg - CMSSW helper to checkout single packages from the git repository in the working area. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-addpkg [options] [ ...] 10 | 11 | .B git cms-addpkg [options] -f FILE 12 | 13 | .SH DESCRIPTION 14 | 15 | This is the git equivalent of the old CVS addpkg command. is the 16 | package you want to checkout (e.g. FWCore/Version), or is the 17 | subsystem you want to checkout (e.g. FWCore). 18 | If the local repository has not been initialized, it will call git-cms-init. 19 | 20 | .SH OPTIONS 21 | 22 | .TP 5 23 | 24 | -d, --debug 25 | 26 | enable debug output 27 | 28 | .TP 5 29 | 30 | -f, --file FILE 31 | 32 | read the list of packages to be checked out from FILE 33 | 34 | .TP 5 35 | 36 | -q, --quiet, -z 37 | 38 | do not print out progress 39 | 40 | .TP 5 41 | 42 | --https 43 | 44 | use https, rather than ssh to access your personal repository 45 | 46 | .TP 5 47 | 48 | --ssh 49 | 50 | use ssh, rather than https to access the official repository 51 | 52 | .TP 5 53 | 54 | -y, --yes 55 | 56 | assume yes to all questions 57 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-checkdeps.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_CHECKDEPS 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-checkdeps - CMSSW helper to checkout packages which need to be recompiled after some change 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-checkdeps [options] 10 | 11 | .SH DESCRIPTION 12 | 13 | Utility to check your local development area against the CMSSW release. 14 | Any modified header files or python modules are found and the package 15 | dependencies of these files will be returned. addpkg-ing these packages 16 | and rebuilding them should provide a full and consistent build. 17 | 18 | .SH OPTIONS 19 | 20 | Notice that by default it will not checkout anything, use -a option to do so. 21 | 22 | .TP 5 23 | 24 | -p 25 | 26 | look for python modules and their dependencies (ON by default) 27 | 28 | .TP 5 29 | 30 | -h 31 | 32 | look for header files and their dependencies (ON by default) 33 | 34 | .TP 5 35 | 36 | -b 37 | 38 | look for BuildFile files and their dependencies (OFF by default) 39 | 40 | .TP 5 41 | 42 | -f 43 | 44 | print name of changed file name instead of type of dependency (OFF by default) 45 | 46 | .TP 5 47 | 48 | -a 49 | 50 | will add/checkout the packages into your development area (OFF by default) 51 | 52 | .TP 5 53 | 54 | -A 55 | 56 | will check all dependencies i.e. header (-h), python(-p) and BuildFile(-b) 57 | 58 | .TP 5 59 | 60 | -d 61 | 62 | do not create dummy copy of deleted files in poison directory. Dummy copies 63 | are useful to find out if deleted headers files are included by other source files. 64 | 65 | .TP 5 66 | 67 | -D 68 | 69 | only dummy copy of deleted files in poison directory created. 70 | NOTE: all other dependency check/add command-line args are ignored. 71 | 72 | .TP 5 73 | 74 | -q 75 | 76 | will pass -Q option to cvs to make it quiet 77 | 78 | .SH POSSIBLE MISBEHAVIORS 79 | 80 | git cms-checkdeps tries to be smart and ignore changes which include a CVS 81 | keyword. However this mean that if on the same line you change a CVS keyword 82 | and something else, these changes will be ignored as well. This in general not 83 | an issue, however there might be corner cases in which you might have used a 84 | CVS keyword in some place where there is also a change actually matters on 85 | the same line. git cms-checkdeps will not spot those. 86 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-checkout-topic.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_CHECKOUT_TOPIC 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-checkout-topic - CMSSW helper to checkout a given branch or pull request into your workarea (without merging). 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-checkout-topic [:]{|} 10 | 11 | .SH OPTIONS 12 | 13 | .TP 5 14 | 15 | -d, --debug 16 | 17 | Enable debug output. 18 | 19 | .TP 5 20 | 21 | --https 22 | 23 | Access GitHub over https (default). 24 | 25 | .TP 5 26 | 27 | --ssh 28 | 29 | Access GitHub over ssh. 30 | 31 | .TP 5 32 | 33 | -o, --old-base 34 | 35 | Specify old base for merge-base or rebase (not used by default). 36 | 37 | .TP 5 38 | 39 | -u, --unsafe 40 | 41 | Do not perform checkdeps at the end of the checkout. 42 | 43 | .SH DESCRIPTION 44 | 45 | This is an alternate mode for git-cms-merge-topic. 46 | It is useful to recreate a working area or setup a patch release, 47 | by checking out only the packages modified 48 | in the specified branch (and their dependencies) without performing a merge. 49 | There are three different syntaxes, depending on whether you want to merge a pull 50 | request (specified via its numeric id, ), a generic branch in 51 | the official-cmssw (https://github.com/cms-sw/cmssw) repository, or a branch in 52 | the repository of some other github user (specified by its github username, 53 | ). 54 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-cvs-history.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_CVS_HISTORY 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-cvs-history CMSSW helper to access CVS historical information. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-cvs-history [options] 10 | 11 | .SH DESCRIPTION 12 | 13 | Git does not support per package tagging, therefore we added a tool to simply 14 | access that information from a standalone repository. 15 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-init.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_INIT 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-init - CMSSW helper to initialize git repository with remotes in working area. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-init [options] [release] 10 | 11 | .SH DESCRIPTION 12 | 13 | This command is equivalent to 'git init' or 'git clone', but 14 | customized for the CMSSW use case. 15 | It initializes the git repository in the src/ folder of the CMSSW working 16 | area, with remotes configured: official-cmssw (upstream) and my-cmssw 17 | (origin, your personal fork). 18 | By default, the current release specified by the environment variable 19 | $CMSSW_BASE is used. An alternative release can be specified as the last argument. 20 | This command may be called by other commands such as cms-addpkg. 21 | 22 | To use a specified protocol (https, ssh, or mixed (default)) 23 | always rather than specifying the flag each time, the git config can be used: 24 | 25 | git config --global cms.protocol ssh 26 | 27 | .SH OPTIONS 28 | 29 | .TP 5 30 | 31 | -d, --debug 32 | 33 | enable debug output 34 | 35 | .TP 5 36 | 37 | --check 38 | 39 | run additional checks on the status of the user repository 40 | 41 | .TP 5 42 | 43 | --https 44 | 45 | use https, rather than ssh to access your personal repository 46 | 47 | .TP 5 48 | 49 | --ssh 50 | 51 | use ssh, rather than https to access the official repository 52 | 53 | .TP 5 54 | 55 | --upstream-only 56 | 57 | configure only the official upstream repository, not the user repository 58 | 59 | .TP 5 60 | 61 | -w, --enable-push 62 | 63 | enable pushing to the official upstream repository 64 | 65 | .TP 5 66 | 67 | -x, --extra NAME 68 | 69 | configure an additional repository at https://github.com/NAME/cmssw with pushing disabled 70 | 71 | .TP 5 72 | 73 | -X, --extra-push NAME 74 | 75 | configure an additional repository at https://github.com/NAME/cmssw with pushing enabled 76 | 77 | .TP 5 78 | 79 | -q, --quiet, -z 80 | 81 | do not print out progress 82 | 83 | .TP 5 84 | 85 | -y, --yes 86 | 87 | assume yes to all questions 88 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-merge-topic.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_MERGE_TOPIC 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-merge-topic - CMSSW helper to merge a given branch or pull request into your workarea. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-merge-topic [:]{|} 10 | 11 | .SH OPTIONS 12 | 13 | .TP 5 14 | 15 | -d, --debug 16 | 17 | Enable debug output. 18 | 19 | .TP 5 20 | 21 | --https 22 | 23 | Access GitHub over https (default). 24 | 25 | .TP 5 26 | 27 | --ssh 28 | 29 | Access GitHub over ssh. 30 | 31 | .TP 5 32 | 33 | --no-backup 34 | 35 | Don't create a backup branch. 36 | 37 | .TP 5 38 | 39 | --backup-name 40 | 41 | Specify suffix for backup branch (default = _backup). 42 | 43 | .TP 5 44 | 45 | --no-commit 46 | 47 | Do not do the final commit when merging. 48 | 49 | .TP 5 50 | 51 | -s, --strategy 52 | 53 | Specify strategy when merging (see git merge documentation). 54 | 55 | .TP 5 56 | 57 | -X, --strategy-option 58 | 59 | Specify strategy option when merging (see git merge documentation). 60 | 61 | .TP 5 62 | 63 | -o, --old-base 64 | 65 | Specify old base for merge-base or rebase (not used by default). 66 | 67 | .TP 5 68 | 69 | -u, --unsafe 70 | 71 | Do not perform checkdeps at the end of the checkout. 72 | 73 | .SH DESCRIPTION 74 | 75 | This is the git equivalent of the old CVS cmstc tagset command. 76 | There are three different syntaxes, depending on whether you want to merge a pull 77 | request (specified via its numeric id, ), a generic branch in 78 | the official-cmssw (https://github.com/cms-sw/cmssw) repository, or a branch in 79 | the repository of some other github user (specified by its github username, 80 | ). 81 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-rebase-topic.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_REBASE_TOPIC 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-rebase-topic - CMSSW helper to rebase a given branch or pull request. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-rebase-topic [:]{|} 10 | 11 | .SH OPTIONS 12 | 13 | .TP 5 14 | 15 | -d, --debug 16 | 17 | Enable debug output. 18 | 19 | .TP 5 20 | 21 | --https 22 | 23 | Access GitHub over https (default). 24 | 25 | .TP 5 26 | 27 | --ssh 28 | 29 | Access GitHub over ssh. 30 | 31 | .TP 5 32 | 33 | --no-backup 34 | 35 | Don't create a backup branch. 36 | 37 | .TP 5 38 | 39 | --backup-name 40 | 41 | Specify suffix for backup branch (default = _backup). 42 | 43 | .TP 5 44 | 45 | -s, --strategy 46 | 47 | Specify strategy when merging (see git merge documentation). 48 | 49 | .TP 5 50 | 51 | -X, --strategy-option 52 | 53 | Specify strategy option when merging (see git merge documentation). 54 | 55 | .TP 5 56 | 57 | -o, --old-base 58 | 59 | Specify old base for merge-base or rebase (not used by default). 60 | 61 | .TP 5 62 | 63 | -n, --new-base 64 | 65 | Specify new base for merge-base or rebase (default = current branch). 66 | 67 | .TP 5 68 | 69 | -u, --unsafe 70 | 71 | Do not perform checkdeps at the end of the checkout. 72 | 73 | .SH DESCRIPTION 74 | 75 | This is an alternate mode for git-cms-merge-topic. 76 | It is useful to rebase a branch or move to a new IB/release, 77 | by checking out only the packages modified 78 | in the specified branch (and their dependencies) and then performing a rebase. 79 | 80 | By default, it uses this rebase syntax: 81 | git rebase [new_base] [branch] 82 | If old_base is specified, it uses this rebase syntax: 83 | git rebase --onto [new_base] [old_base] [branch] 84 | If you want access to advanced options for rebase, use git-cms-checkout-topic 85 | and then call git rebase manually. 86 | 87 | There are three different syntaxes, depending on whether you want to merge a pull 88 | request (specified via its numeric id, ), a generic branch in 89 | the official-cmssw (https://github.com/cms-sw/cmssw) repository, or a branch in 90 | the repository of some other github user (specified by its github username, 91 | ). 92 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-rmpkg.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_RMPKG 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-rmpkg - CMSSW helper to remove (un-checkout) single packages or subsystems from the git repository in the working area. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-rmpkg [options] [ ...] 10 | 11 | .B git cms-rmpkg [options] -f FILE 12 | 13 | .SH DESCRIPTION 14 | 15 | This command can undo the actions of the git-cms-addpkg command, 16 | removing (e.g. FWCore/Version) or (e.g. FWCore) 17 | from your working area (but NOT from the repository itself). 18 | This is useful if you decide you do not want to recompile the package/subsystem, 19 | but instead to use the precompiled library for the release. 20 | 21 | .SH OPTIONS 22 | 23 | .TP 5 24 | 25 | -d, --debug 26 | 27 | enable debug output 28 | 29 | .TP 5 30 | 31 | -f, --file FILE 32 | 33 | read the list of packages to be checked out from FILE 34 | 35 | .TP 5 36 | 37 | -q, --quiet, -z 38 | 39 | do not print out progress 40 | 41 | .TP 5 42 | 43 | -o, --force 44 | 45 | force removal of packages even if modified or containing untracked files 46 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-showtags.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_SHOWTAGS 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-showtags - Show which packages have changed with respect to the release. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-showtags 10 | 11 | .SH DESCRIPTION 12 | 13 | When invoked it will show the packages in the current area which have changed 14 | with respect to the release and a unique identifier (a git tree object hash) 15 | for the old and new version. 16 | -------------------------------------------------------------------------------- /docs/man/man1/git-cms-squash-topic.1: -------------------------------------------------------------------------------- 1 | .TH GIT_CMS_SQUASH_TOPIC 1 LOCAL 2 | 3 | .SH NAME 4 | 5 | git-cms-squash-topic - CMSSW helper to squash commits in a given branch. 6 | 7 | .SH SYNOPSIS 8 | 9 | .B git cms-squash-topic [[:]{|}] 10 | 11 | .SH OPTIONS 12 | 13 | .TP 5 14 | 15 | -d, --debug 16 | 17 | Enable debug output. 18 | 19 | .TP 5 20 | 21 | --https 22 | 23 | Access GitHub over https (default). 24 | 25 | .TP 5 26 | 27 | --ssh 28 | 29 | Access GitHub over ssh. 30 | 31 | .TP 5 32 | 33 | --no-backup 34 | 35 | Don't create a backup branch. 36 | 37 | .TP 5 38 | 39 | --backup-name 40 | 41 | Specify suffix for backup branch (default = _backup). 42 | 43 | .TP 5 44 | 45 | -o, --old-base 46 | 47 | Specify old base for merge-base or rebase (not used by default). 48 | 49 | .TP 5 50 | 51 | -u, --unsafe 52 | 53 | Do not perform checkdeps at the end of the checkout. 54 | 55 | .TP 5 56 | 57 | --current 58 | 59 | Squash the current branch. (implies --unsafe and --old-base $CMSSW_VERSION) 60 | 61 | .TP 5 62 | 63 | -m, --message 64 | 65 | Specify new message for squashed commit (instead of using prepopulated message from original commits) 66 | 67 | .SH DESCRIPTION 68 | 69 | This is an alternate mode for git-cms-merge-topic. 70 | It is useful to squash a PR branch if requested by the release manager 71 | or if desired by the developer. 72 | 73 | It can squash the current branch using the --current option. 74 | If a remote branch is specified, git-cms-checkout-topic will automatically be performed for that branch. 75 | 76 | To squash only a subset of the newest commits in a branch, change the --old-base value. 77 | (Squashing intermediate commits, i.e. a subset that does not extend to the newest commits, 78 | is not part of this tool; that operation requires the use of interactive rebase, i.e. git rebase -i.) 79 | -------------------------------------------------------------------------------- /git-cms-addpkg: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | # Mimics addpkg behavior in git. 3 | 4 | case `uname` in 5 | Darwin) 6 | ECHO="echo" ;; 7 | *) 8 | ECHO="echo -e" ;; 9 | esac 10 | 11 | usage () { 12 | COMMAND_NAME=$1 13 | $ECHO "git $COMMAND_NAME [options] Subsystem/Package [Subsystem/Package ...] " 14 | $ECHO "git $COMMAND_NAME [options] -f FILE" 15 | $ECHO 16 | $ECHO "Options:" 17 | $ECHO "-h, --help \tthis help message" 18 | $ECHO 19 | $ECHO "-d, --debug \tenable debug output" 20 | $ECHO "-f, --file FILE \tread the list of packages to be checked out from FILE" 21 | $ECHO "-q, --quiet, -z \tdo not print out progress" 22 | if [ "$COMMAND_NAME" == "cms-addpkg" ]; then 23 | $ECHO " --https \tuse https, rather than ssh to access your personal repository" 24 | $ECHO " --ssh \tuse ssh, rather than https to access the official repository" 25 | $ECHO "-y, --yes \tassume yes to all questions" 26 | elif [ "$COMMAND_NAME" == "cms-rmpkg" ]; then 27 | $ECHO "-o, --force \tforce removal of packages even if modified or containing untracked files" 28 | fi 29 | exit $2 30 | } 31 | 32 | COMMAND_NAME=$(basename $0 | sed -e's/^git-//') 33 | ACTION="Checking out" 34 | if [ "$COMMAND_NAME" = "cms-rmpkg" ]; then 35 | RMPKG=true 36 | ACTION="Removing" 37 | fi 38 | 39 | DEBUG=0 40 | VERBOSE=1 41 | INITOPTIONS="" # options passed to git cms-init 42 | PACKAGES= 43 | INPUT_FILE= 44 | FORCE= 45 | 46 | # colors and formatting 47 | RED='\033[31m' 48 | NORMAL='\033[0m' 49 | 50 | verbose () { 51 | if [ "X$VERBOSE" = X1 ]; then 52 | $ECHO "$@" 53 | fi 54 | } 55 | 56 | while [ "$#" != 0 ]; do 57 | case "$1" in 58 | -h | --help ) 59 | usage $COMMAND_NAME 0;; 60 | -d | --debug ) 61 | INITOPTIONS="$INITOPTIONS $1" 62 | shift; set -x; DEBUG=1 ;; 63 | -f | --file ) 64 | OPTION=$1; shift 65 | INPUT_FILE="$1"; shift 66 | if [ ! "$INPUT_FILE" ]; then 67 | $ECHO "git cms-addpkg: option $OPTION requires an argument" 68 | $ECHO 69 | usage 1 70 | elif [ ! -r "$INPUT_FILE" ]; then 71 | $ECHO "git cms-addpkg: file $INPUT_FILE does not exist or is not readable" 72 | $ECHO 73 | usage $COMMAND_NAME 1 74 | fi 75 | unset OPTION 76 | ;; 77 | -q | --quiet | -z ) 78 | INITOPTIONS="$INITOPTIONS $1" 79 | shift; set +x; DEBUG=0; VERBOSE=0 ;; 80 | -y | --yes ) 81 | INITOPTIONS="$INITOPTIONS $1" 82 | shift;; 83 | --https ) 84 | INITOPTIONS="$INITOPTIONS $1" 85 | shift;; 86 | --ssh ) 87 | INITOPTIONS="$INITOPTIONS $1" 88 | shift;; 89 | -o | --force ) 90 | FORCE=true 91 | shift;; 92 | -*) 93 | $ECHO "git cms-addpkg: unknown option $1"; $ECHO; usage $COMMAND_NAME 1;; 94 | *) 95 | if [ "$INPUT_FILE" == "" ]; then 96 | # check out a list of packages 97 | PACKAGES="$PACKAGES $1" 98 | shift 99 | else 100 | # check out a list of packages via -f / --file FILE 101 | $ECHO "git $COMMAND_NAME: you cannot specify a package and input from file at the same time." 102 | $ECHO 103 | usage $COMMAND_NAME 1 104 | fi 105 | ;; 106 | esac 107 | done 108 | if [ "$PACKAGES" == "" ] && [ "$INPUT_FILE" == "" ] ; then 109 | $ECHO "git $COMMAND_NAME: you need to specify at least one package or input file." 110 | $ECHO 111 | usage $COMMAND_NAME 1 112 | fi 113 | 114 | checkPkgs () { 115 | PACKAGES="$1" 116 | CURRENT_BRANCH="$2" 117 | for PKG_NAME in $PACKAGES; do 118 | if [ ! -d "$CMSSW_BASE/src/$PKG_NAME" ]; then 119 | [ "$HEADER" ] || { $ECHO "\nThese packages do not exist in branch $CURRENT_BRANCH"; HEADER=done; } 120 | echo $PKG_NAME 121 | fi 122 | done 123 | if [ "$COMMAND_NAME" == "cms-rmpkg" ]; then 124 | for PKG_NAME in $PACKAGES; do 125 | UNTK=`git clean -xdn $CMSSW_BASE/src/$PKG_NAME` 126 | if [ -n "$UNTK" ]; then 127 | [ "$HEADER2" ] || { $ECHO "\nThese packages contain untracked files"; HEADER2=done; } 128 | echo $PKG_NAME 129 | if [ -n "$FORCE" ]; then 130 | git clean -xdf $CMSSW_BASE/src/$PKG_NAME > /dev/null 2>&1 131 | fi 132 | fi 133 | done 134 | MODPKG=`git diff --name-only $CMSSW_VERSION..HEAD | cut -d'/' -f1-2 | sort -u` 135 | for PKG_NAME in $PACKAGES; do 136 | if [[ "$MODPKG" =~ "$PKG_NAME" ]]; then 137 | [ "$HEADER3" ] || { $ECHO "\nThese packages have been modified from the base release"; HEADER3=done; } 138 | echo $PKG_NAME 139 | fi 140 | done 141 | fi 142 | if [ "$HEADER" ] || (([ "$HEADER2" ] || [ "$HEADER3" ]) && [ -z "$FORCE" ]); then 143 | exit 1 144 | fi 145 | } 146 | 147 | BASH_FULL_VERSION=$((${BASH_VERSINFO[0]} * 10000 + ${BASH_VERSINFO[1]} * 100 + ${BASH_VERSINFO[2]})) 148 | if (( BASH_FULL_VERSION >= 40100 )); then 149 | # bash 4.1 or newer 150 | if [ $VERBOSE == 0 ]; then 151 | # send verbose messages to /dev/null 152 | exec {verbose}> /dev/null 153 | else 154 | # send debug messages to stderr 155 | exec {verbose}>&2 156 | fi 157 | if [ $DEBUG == 0 ]; then 158 | # send debug messages to /dev/null 159 | exec {debug}> /dev/null 160 | else 161 | # send debug messages to stderr 162 | exec {debug}>&2 163 | fi 164 | else 165 | # bash 4.0 or older 166 | verbose=11 167 | if [ $VERBOSE == 0 ]; then 168 | # send verbose messages to /dev/null 169 | exec 11> /dev/null 170 | else 171 | # send debug messages to stderr 172 | exec 11>&2 173 | fi 174 | debug=12 175 | if [ $DEBUG == 0 ]; then 176 | # send debug messages to /dev/null 177 | exec 12> /dev/null 178 | else 179 | # send debug messages to stderr 180 | exec 12>&2 181 | fi 182 | fi 183 | 184 | if [ "$INPUT_FILE" ]; then 185 | # make it into a standard package list 186 | PACKAGES=`cat "$INPUT_FILE" | sed -e's|\s*#.*||' | grep -v '^\s*$'` 187 | # check the syntax of the input file 188 | INVALID=`echo $PACKAGES | tr " " "\n" | grep -v -E '^/*\w+(/\w+)?/*$' || true` 189 | if [ -n "$INVALID" ]; then 190 | $ECHO "Some lines of $INPUT_FILE are not in a valid format:" 191 | $ECHO "$RED$INVALID$NORMAL" 192 | exit 1 193 | fi 194 | unset INVALID 195 | fi 196 | 197 | # initialize the local repository 198 | if [ -z "$CMSSW_BASE" ]; then 199 | $ECHO "CMSSW environment not setup, please run 'cmsenv' before 'git $COMMAND_NAME'." 200 | exit 1 201 | fi 202 | if ! [ -d $CMSSW_BASE/src/.git ]; then 203 | if [ "$COMMAND_NAME" == "cms-rmpkg" ]; then 204 | $ECHO "git $COMMAND_NAME : nothing to do." 205 | exit 1 206 | else 207 | git cms-init $INITOPTIONS 208 | fi 209 | fi 210 | 211 | cd $CMSSW_BASE/src 212 | 213 | case `git --version` in 214 | git\ version\ 1.7*) 215 | # git 1.7.x does not support a leading slash in .gitignore and .git/info/sparse-checkout 216 | LEADING_SLASH= 217 | ;; 218 | *) 219 | LEADING_SLASH=/ 220 | ;; 221 | esac 222 | 223 | # check if using a reference repository 224 | if [ "$CMSSW_GIT_REFERENCE" == "" ] && [ -f $CMSSW_BASE/src/.git/objects/info/alternates ]; then 225 | CMSSW_GIT_REFERENCE=`cat $CMSSW_BASE/src/.git/objects/info/alternates | head -n1` 226 | fi 227 | 228 | if [ "$(git status --porcelain --untracked=no | grep '^[ACDMRU]')" ]; then 229 | $ECHO "${RED}Error:${NORMAL} there are staged but not committed changes on your working tree, please commit or stash them." 230 | exit 1 231 | fi 232 | 233 | CURRENT_BRANCH=`git symbolic-ref --short HEAD` 234 | 235 | # check if requested packages are present to be removed 236 | if [ "$COMMAND_NAME" == "cms-rmpkg" ]; then 237 | checkPkgs "$PACKAGES" "$CURRENT_BRANCH" 238 | fi 239 | 240 | # create temporary sparse checkout file 241 | touch $CMSSW_BASE/src/.git/info/sparse-checkout-tmp 242 | 243 | # add the requested package(s) to the temporary file 244 | verbose "\n$ACTION packages" 245 | for PKG_NAME in $PACKAGES; do 246 | verbose $PKG_NAME 247 | echo $PKG_NAME | sed -e "s|[/]*$|/|;s|^/*|${LEADING_SLASH}|" >> $CMSSW_BASE/src/.git/info/sparse-checkout-tmp 248 | done 249 | 250 | # add or remove from the real sparse checkout file 251 | if [ "$COMMAND_NAME" == "cms-addpkg" ]; then 252 | cat $CMSSW_BASE/src/.git/info/sparse-checkout-tmp | while read LINE; do 253 | # remove any exclusion line(s) 254 | grep -v "^\!$LINE" $CMSSW_BASE/src/.git/info/sparse-checkout > $CMSSW_BASE/src/.git/info/sparse-checkout-new 255 | mv $CMSSW_BASE/src/.git/info/sparse-checkout-new $CMSSW_BASE/src/.git/info/sparse-checkout 256 | # if addition line not present, append it 257 | if ! grep -q -x "$LINE" $CMSSW_BASE/src/.git/info/sparse-checkout; then 258 | echo "$LINE" >> $CMSSW_BASE/src/.git/info/sparse-checkout 259 | fi 260 | done 261 | else 262 | cat $CMSSW_BASE/src/.git/info/sparse-checkout-tmp | while read LINE; do 263 | # remove any addition line(s) 264 | grep -v "^$LINE" $CMSSW_BASE/src/.git/info/sparse-checkout > $CMSSW_BASE/src/.git/info/sparse-checkout-new 265 | mv $CMSSW_BASE/src/.git/info/sparse-checkout-new $CMSSW_BASE/src/.git/info/sparse-checkout 266 | # special case: append exclusion line for package (if whole subsystem previously added) 267 | if echo $LINE | grep -q "${LEADING_SLASH}.*/.*/"; then 268 | SUBSYSTEM=${LINE%/*/}/ 269 | if grep -q -x "$SUBSYSTEM" $CMSSW_BASE/src/.git/info/sparse-checkout; then 270 | echo "!$LINE" >> $CMSSW_BASE/src/.git/info/sparse-checkout 271 | fi 272 | fi 273 | done 274 | fi 275 | rm -f $CMSSW_BASE/src/.git/info/sparse-checkout-tmp 276 | 277 | # sort, keep exclusion lines at end 278 | grep -v "^\!" $CMSSW_BASE/src/.git/info/sparse-checkout | sort -u > $CMSSW_BASE/src/.git/info/sparse-checkout-new 279 | grep "^\!" $CMSSW_BASE/src/.git/info/sparse-checkout | sort -u >> $CMSSW_BASE/src/.git/info/sparse-checkout-new 280 | mv $CMSSW_BASE/src/.git/info/sparse-checkout-new $CMSSW_BASE/src/.git/info/sparse-checkout 281 | 282 | # update the working area 283 | git read-tree -mu HEAD 284 | 285 | # check if requested packages were successfully added 286 | if [ "$COMMAND_NAME" == "cms-addpkg" ]; then 287 | checkPkgs "$PACKAGES" "$CURRENT_BRANCH" 288 | exit 0 289 | fi 290 | -------------------------------------------------------------------------------- /git-cms-checkdeps: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | """:" 4 | python_cmd="python" 5 | python3 -V >/dev/null 2>&1 && python_cmd="python3" 6 | exec ${python_cmd} $0 ${1+"$@"} 7 | """ 8 | 9 | import sys 10 | import re 11 | import gzip 12 | import tempfile 13 | import shutil 14 | import subprocess 15 | from os import path, symlink, environ, chdir, makedirs, remove 16 | from optparse import OptionParser 17 | 18 | # Idea: diff checked out packages. 19 | # looking for changed headers 20 | # find all packages that depend on those headers 21 | # print that list. 22 | 23 | poisondir = "poison" 24 | help_text = "\n\ 25 | Utility to check your local development area against the CMSSW release.\n\ 26 | Any modified header files or python modules are found and the package \n\ 27 | dependencies of these files will be returned. addpkg-ing these packages\n\ 28 | and rebuilding them should provide a full and consistent build." 29 | 30 | parser = OptionParser(description=help_text, conflict_handler="resolve") 31 | parser.add_option("-a", dest="checkout", default=False, action="store_true", 32 | help="will add/checkout the packages into your development area", metavar=" ") 33 | parser.add_option("-p", dest="checkpython", default=False, action="store_true", 34 | help="look for python modules and their dependencies (ON by default)", metavar=" ") 35 | parser.add_option("-h", dest="checkheader", default=False, action="store_true", 36 | help="look for header files and their dependencies (ON by default)", metavar=" ") 37 | parser.add_option("-b", dest="checkbuildfile", default=False, action="store_true", 38 | help="look for BuildFile files and their dependencies (OFF by default)", metavar=" ") 39 | parser.add_option("-f", dest="printFileNames", default=False, action="store_true", 40 | help="print name of changed file name instead of type of dependency (OFF by default)", metavar=" ") 41 | parser.add_option("-d", dest="poison_includes", default=False, action="store_false", 42 | help="do not create dummy copy of deleted files in %s directory. Dummy copies\ 43 | are useful to find out if deleted headers files are included by other source files." % poisondir, metavar=" ") 44 | parser.add_option("-D", dest="poison_only", default=False, action="store_true", 45 | help="only dummy copy of deleted files in %s directory created.\ 46 | NOTE: all other dependency check/add command-line args are ignored." % poisondir, metavar=" ") 47 | parser.add_option("-A", dest="all", action="store_true", 48 | help="will check all dependencies i.e. header (-h), python(-p) and BuildFile(-b)", metavar=" ") 49 | 50 | (options, args) = parser.parse_args() 51 | 52 | checkout = options.checkout 53 | checkpython = options.checkpython 54 | checkheader = options.checkheader 55 | checkbuildfile = options.checkbuildfile 56 | printFileNames = options.printFileNames 57 | poison_includes = options.poison_includes 58 | poison_only = options.poison_only 59 | all = options.all 60 | 61 | if checkout: 62 | if not poison_includes: 63 | poison_includes = True 64 | if all: 65 | checkpython = checkheader = checkbuildfile = True 66 | 67 | if poison_only: 68 | checkpython = False 69 | checkheader = False 70 | checkbuildfile = False 71 | checkout = False 72 | poison_includes = True 73 | elif (not checkpython) & (not checkheader) & (not checkbuildfile): 74 | checkpython = True 75 | checkheader = True 76 | 77 | try: 78 | localtop = environ["CMSSW_BASE"] 79 | except KeyError: 80 | print("ERROR: Could not find developer area base path. Please run \"cmsenv\" in a developer area.") 81 | sys.exit(1) 82 | 83 | try: 84 | releasetop = environ["CMSSW_RELEASE_BASE"] 85 | except KeyError: 86 | print("ERROR: Could not find release base path. Please run this script from a developer area.") 87 | sys.exit(1) 88 | 89 | vals = {} 90 | changedFiles = [] 91 | deletedFiles = [] 92 | upackages = {} 93 | 94 | 95 | def readDependencyInfo(file, cache): 96 | global vals 97 | for line in gzip.open(file).readlines(): 98 | line = line.decode('utf-8').rstrip('\n') 99 | file1, rest = line.split(' ', 1) 100 | if file1 != "": 101 | deps = [d for d in rest.split(' ') if d] 102 | if not deps: continue 103 | if file1 not in vals: 104 | vals[file1] = [] 105 | vals[file1].extend(deps) 106 | 107 | 108 | def poisonIncludes(deletedFiles, topdir): 109 | poison = path.join(topdir, poisondir) 110 | if path.isdir(poison): 111 | shutil.rmtree(poison) 112 | poisondata = path.join(poison, ".data") 113 | makedirs(poisondata) 114 | if len(deletedFiles) > 0: 115 | print(">> Creating dummy files under %s directory." % poison) 116 | for file in deletedFiles: 117 | f = path.join(poison, file) 118 | dir = path.dirname(f) 119 | if not path.isdir(dir): 120 | makedirs(dir) 121 | if re.search(r'\/data\/', file): 122 | symlink(poisondata, f) 123 | else: 124 | try: 125 | with open(f, "w") as xfile: 126 | xfile.write( 127 | "#error THIS FILE HAS BEEN REMOVED FROM THE PACKAGE.\n") 128 | except Exception as e: 129 | print(e, "\nERROR: Can not open file for writing: %s\n" % f) 130 | print(" %s" % file) 131 | 132 | 133 | if checkheader: 134 | depfile = "%s/etc/dependencies/usedby.out.gz" % releasetop 135 | if path.isfile(depfile): 136 | readDependencyInfo(depfile, vals) 137 | else: 138 | print("ERROR: This release appears not to support the functionality of this script (170pre4 and higher). Sorry") 139 | 140 | if checkpython: 141 | depfile = "%s/etc/dependencies/pyusedby.out.gz" % releasetop 142 | if path.isfile(depfile): 143 | readDependencyInfo(depfile, vals) 144 | 145 | if checkbuildfile: 146 | depfile = "%s/etc/dependencies/bfusedby.out.gz" % releasetop 147 | if path.isfile(depfile): 148 | readDependencyInfo(depfile, vals) 149 | 150 | chdir("%s/src" % localtop) 151 | reltag = None 152 | if environ.get("CMSSW_GIT_HASH"): 153 | reltag = environ["CMSSW_GIT_HASH"] 154 | else: 155 | reltag = environ["CMSSW_VERSION"] 156 | 157 | args_0 = ['git', 'diff', '''-G^([^$]+$|[^$]*[$][^$]*$|([^$]*[$])($|[^RAIDLNSH]|(R[^eC]|A[^u]|I[^d]|D[^a]|L[^o]| 158 | N[^a]|S[^o]|H[^e])|(Re[^v]|RC[^S]|Au[^t]|Id[^:]|Da[^t]|Lo[^g]|Na[^m]|So[^u]|He[^a])|(Rev[^i]|RCS[^f]|Aut[^h]| 159 | Dat[^e]|Log[^:]|Nam[^e]|Sou[^r]|Hea[^d])|(Revi[^s]|RCSf[^i]|Auth[^o]|Date[^:]|Name[^:]|Sour[^c]|Head[^e])| 160 | (Revis[^i]|RCSfi[^l]|Autho[^r]|Sourc[^e]|Heade[^r])|(Revisi[^o]|RCSfil[^e]|Author[^:]|Source[^:]|Header[^:])| 161 | (Revisio[^n]|RCSfile[^:])|(Revision[^:])))''', '--name-status', '-r', reltag] 162 | args_1 = ['grep', '-v', '.gitignore'] 163 | args_2 = ['sed', '-e', 's/[ \\t]\\+/ /'] 164 | args_3 = ['git', 'diff', '--diff-filter', 'R', '--name-status', '-r', reltag] 165 | pipe_0 = subprocess.Popen(args_0, stdout=subprocess.PIPE) 166 | pipe_1 = subprocess.Popen(args_1, stdin=pipe_0.stdout, stdout=subprocess.PIPE) 167 | pipe_2 = subprocess.Popen(args_2, stdin=pipe_1.stdout, stdout=subprocess.PIPE) 168 | pipe_3 = subprocess.Popen(args_3, stdout=subprocess.PIPE) 169 | stdout = pipe_2.communicate()[0].splitlines() 170 | stdout.extend(pipe_3.communicate()[0].splitlines()) 171 | for diff in stdout: 172 | diff = diff.decode() 173 | match = re.search( 174 | r'^[MUDR]([0-9]*)\s+([^\/]+\/[^\/]+)\/[^\s]+(\s+[^\/]+\/[^\/]+\/[^\s]+|)$', diff) 175 | if match: 176 | pack = match.group(2) 177 | if not pack in upackages: 178 | upackages[pack] = [] 179 | if not path.exists(pack): 180 | print(">> Package removed %s" % pack) 181 | upackages[pack].append(diff) 182 | 183 | packages = sorted(upackages) 184 | for package in packages: 185 | if re.search(r'^UserCode.*', package): 186 | continue 187 | print(">> Checking %s %s" % (package, reltag)) 188 | msgs = {"-": {}, "x": {}} 189 | for diff in upackages[package]: 190 | _del = None 191 | match = re.search(r'^(R[0-9]*)\s+([^\s]+)\s+', diff) 192 | if match: 193 | diff = "D %s" % match.group(2) 194 | match_M = re.search(r'^(M)', diff) 195 | match_U = re.search(r'^(U)', diff) 196 | match_D = re.search(r'^(D)', diff) 197 | if match_M or match_U or match_D: 198 | for match in [match_M, match_U, match_D]: 199 | if match: 200 | if match.group() == "D": 201 | _del = 1 202 | sp2 = diff.split(' ') 203 | diff = sp2[1] 204 | else: 205 | diff = None 206 | if diff: 207 | msgs["x"][diff] = 1 208 | if _del: 209 | msgs["-"][diff] = 1 210 | files = sorted(msgs["-"].keys()) 211 | deletedFiles.extend(files) 212 | changedFiles.extend(files) 213 | for diff in files: 214 | print(" - %s" % diff) 215 | del msgs["x"][diff] 216 | files = sorted(msgs["x"].keys()) 217 | changedFiles.extend(files) 218 | for diff in files: 219 | print(" x %s" % diff) 220 | 221 | if poison_includes: 222 | poisonIncludes(deletedFiles, localtop) 223 | if poison_only: 224 | sys.exit(0) 225 | 226 | recompileList = {} 227 | big_bf = "" 228 | for file in changedFiles: 229 | if re.search(r'^BigProducts\/[^\/]+\/BuildFile\.xml$', file): 230 | big_bf = "%s %s" % (big_bf, file) 231 | if file not in vals: 232 | continue 233 | for dep in vals[file]: 234 | sp = dep.split("/") 235 | try: 236 | recompile = "%s/%s" % (sp[0], sp[1]) 237 | except IndexError: 238 | recompile = "" 239 | if not list(filter(lambda x: recompile==x, packages)): 240 | scope = "header" 241 | if re.search(r'\.py$', file): 242 | scope = "python" 243 | elif re.search(r'\/BuildFile(\.xml|)$', file): 244 | scope = "buildfile" 245 | if recompile not in recompileList: 246 | recompileList[recompile] = {} 247 | if scope not in recompileList[recompile]: 248 | recompileList[recompile][scope] = {} 249 | recompileList[recompile][scope] = file 250 | 251 | if big_bf: 252 | pipe_0 = subprocess.Popen(["git", "diff","-r", reltag, "--", big_bf.strip()], stdout=subprocess.PIPE) 253 | for diff in [l.decode() for l in pipe_0.communicate()[0].splitlines()]: 254 | if not diff.startswith('+'): 255 | next 256 | diff = re.sub(r'^[+]', r'', diff) 257 | for p in diff.split(">"): 258 | match = re.search(r'^\s*<\s*use\s+name\s*=\s*["]([^"]+)["]\s*', p, re.I) 259 | if match: 260 | if path.exists("%s/src/%s" % (releasetop, match.group(1))): 261 | pack = match.group(1) 262 | if not pack in recompileList: 263 | recompileList[pack]= {} 264 | recompileList[pack]["biglib"] = "BigProducts" 265 | 266 | t = sorted(recompileList.keys()) 267 | len = len(t) 268 | if not checkout: 269 | print("Packages to check out and compile: %s" % len) 270 | else: 271 | print("Checking out these packages: %s" % len) 272 | 273 | exitcode = 0 274 | if len > 0: 275 | for pk in t: 276 | if printFileNames: 277 | print("%s (%s)" % 278 | (pk, ', '.join(sorted(recompileList[pk].values())))) 279 | else: 280 | print("%s (%s)" % 281 | (pk, ', '.join(sorted(recompileList[pk].keys())))) 282 | if checkout: 283 | chdir(localtop) 284 | temp_path = path.join(environ["CMSSW_BASE"], "tmp") 285 | tempfile.tempdir = temp_path 286 | temp = tempfile.NamedTemporaryFile(prefix="checkdeps", mode="w",delete=False) 287 | fname = temp.name 288 | for pk in t: 289 | temp.write(pk + "\n") 290 | temp.close() 291 | chdir("%s/src" % localtop) 292 | process = subprocess.Popen(['git', 'cms-addpkg', '-f', fname, '-q']) 293 | process.wait() 294 | exitcode = + process.returncode 295 | remove(fname) 296 | if exitcode: 297 | exitcode = 1 298 | sys.exit(exitcode) 299 | -------------------------------------------------------------------------------- /git-cms-checkout-topic: -------------------------------------------------------------------------------- 1 | git-cms-merge-topic -------------------------------------------------------------------------------- /git-cms-cherry-pick-pr: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | function usage() { 4 | cat <<@EOF 5 | Usage: git cms-cherry-pick-pr [] 6 | 7 | Description: 8 | Cherry pick the commits that compose pull request that has been opened or merged 9 | in the master branch, or in if it is specified. 10 | @EOF 11 | exit $1 12 | } 13 | 14 | # the number of the pull request 15 | PULL=$1 16 | [ "$PULL" ] || usage 1 17 | 18 | # for a backport, specify the target branch that was used 19 | BRANCH=$2 20 | [ "$BRANCH" ] || BRANCH=master 21 | 22 | # FIXME add an option to support alternate repositories ? 23 | REMOTE="official-cmssw" 24 | 25 | [ "$CMSSW_BASE" ] && cd $CMSSW_BASE/src 26 | 27 | # fetch the master branch from upstream 28 | git fetch -q $REMOTE $BRANCH 29 | 30 | # fetch the pull request 31 | git fetch -q $REMOTE pull/$PULL/head 32 | 33 | # find the branch point 34 | BRANCH_POINT=$(diff -u <(git rev-list --first-parent FETCH_HEAD) <(git rev-list --first-parent $REMOTE/$BRANCH) | sed -ne 's/^ //p' | head -n1 -) 35 | 36 | # show the commits in the pull request 37 | git cherry-pick FETCH_HEAD...$BRANCH_POINT 38 | -------------------------------------------------------------------------------- /git-cms-cvs-history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from commands import getstatusoutput 3 | from optparse import OptionParser 4 | from sys import exit 5 | from os import environ, chdir 6 | from os.path import exists, join 7 | import re 8 | 9 | def format(s, **kwds): 10 | return s % kwds 11 | 12 | def die(s, verbose=None): 13 | print s 14 | if verbose: 15 | print verbose 16 | exit(1) 17 | 18 | def findSymbol(tag, package): 19 | cmssw_base = environ["CMSSW_BASE"] 20 | if tag == "HEAD": 21 | tag = "master" 22 | if tag != "master": 23 | branchAttempt = format("refs/remotes/%(package)s/%(package)s-%(tag)s", 24 | package=package, 25 | tag=tag) 26 | else: 27 | branchAttempt = format("refs/remotes/%(package)s/master", 28 | package=package, 29 | tag=tag) 30 | tagAttempt = format("refs/tags/%(package)s-%(tag)s", 31 | package=package, 32 | tag=tag) 33 | if exists(join(cmssw_base, "src/.git", branchAttempt)): 34 | tag = branchAttempt 35 | elif exists(join(cmssw_base, "src/.git", tagAttempt)): 36 | tag = tagAttempt 37 | else: 38 | print branchAttempt 39 | die("Unable to find symbol %s for package %s." % (tag, realPackage)) 40 | return tag 41 | 42 | if __name__ == "__main__": 43 | parser = OptionParser(usage="git cms-cvs-history diff [..] SubSystem/Package\n" 44 | " import SubSystem/Package\n" 45 | " tags SubSystem/Package\n" 46 | " log SubSystem/Package") 47 | opts, args = parser.parse_args() 48 | if len(args) < 1: 49 | parser.error("`git cms-cvs-history' requires either `import`, `diff', `tags' or `log' sub-command") 50 | if len(args) == 1: 51 | parser.error("`git cms-cvs-history' requires %s requires a package" % args[0]) 52 | command = args[0] 53 | 54 | if not command in ["diff", "import", "log", "tags"]: 55 | parser.error("`git cms-cvs-history' requires either `import`, `diff' or `log' sub-command") 56 | 57 | cmssw_base = environ.get("CMSSW_BASE", None) 58 | if not cmssw_base: 59 | die("Please setup your CMSSW area") 60 | 61 | chdir(join(cmssw_base, "src")) 62 | 63 | err, output = getstatusoutput(format("cd $CMSSW_BASE/src ; git init")) 64 | if err: 65 | die("Error while setting up git repository") 66 | # The last arg should be the package 67 | realPackage = args[-1] 68 | package = args[-1].replace("/","-") 69 | err, output = getstatusoutput("git remote show | grep %s" % package) 70 | if err: 71 | err, output = getstatusoutput(format("git remote add %(package)s git@github.com:cms-cvs-history/%(package)s.git", 72 | package=package)) 73 | if err: 74 | die("Error while adding repository", output) 75 | 76 | err, output = getstatusoutput(format("git fetch %(package)s ;" 77 | "git fetch %(package)s --tags", package=package)) 78 | if err: 79 | err, output2 = getstatusoutput(format("git remote rm %(package)s", 80 | package=package)) 81 | die("Could not fetch info for package package %s." % package, output) 82 | 83 | # Poor man command dispatcher.. 84 | if command == "diff": 85 | if len(args) != 3: 86 | parser.error("diff requires [..] ") 87 | diffArgs = args[1] 88 | tags = diffArgs.split("..") 89 | if len(tags) == 1: 90 | tags.append("HEAD") 91 | 92 | tags[0] = findSymbol(tags[0], package) 93 | tags[1] = findSymbol(tags[1], package) 94 | 95 | err, output = getstatusoutput("git diff %s..%s" % (tags[0], tags[1])) 96 | if err: 97 | die("Could not create diff", output) 98 | print output 99 | exit(0) 100 | elif command == "tags": 101 | if len(args) == 1: 102 | parser.error("Please specify a package") 103 | err, output = getstatusoutput(format("git tag | grep -e '^%(package)s' | sed -e's/^%(package)s-//'", 104 | package=package)) 105 | print output 106 | exit(0) 107 | elif command == "import": 108 | tag = "master" 109 | if len(args) == 3: 110 | tag = args[1] 111 | elif len(args) != 2: 112 | parser.error("`import` takes only and as arguments.") 113 | tag = findSymbol(tag, package) 114 | command = format("mkdir -p $CMSSW_BASE/src/%(realPackage)s &&" 115 | "cd $CMSSW_BASE/src &&" 116 | "git archive --format=tar %(tag)s | (cd $CMSSW_BASE/src/%(realPackage)s ; tar xf -)", 117 | package=package, 118 | tag=tag, 119 | realPackage=realPackage) 120 | err, output = getstatusoutput(command) 121 | if err: 122 | die("Error while checking out %s" % realPackage, output) 123 | exit(0) 124 | elif command == "log": 125 | tag = "master" 126 | if len(args) == 3: 127 | tag = args[1] 128 | err, output = getstatusoutput("git log refs/remotes/%s/%s" % (package, tag)) 129 | if err: 130 | die("Error while doing git log", output) 131 | print output 132 | -------------------------------------------------------------------------------- /git-cms-fetch-pr: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | function usage() { 4 | cat <<@EOF 5 | Usage: git cms-fetch-pr [] 6 | 7 | Description: 8 | Fetch a pull request from https://github.com/cms-sw/cmssw.git into the local branch 9 | pull/ , or if specified. 10 | @EOF 11 | exit $1 12 | } 13 | 14 | PULL= 15 | BRANCH= 16 | 17 | while [ "$#" != 0 ]; do 18 | case "$1" in 19 | -*) 20 | echo Unknown option $1 21 | usage 1 22 | ;; 23 | *) 24 | if [ "$PULL" == "" ]; then 25 | PULL=$1 26 | elif [ "$BRANCH" == "" ]; then 27 | BRANCH=$1 28 | else 29 | echo Unexpected argument $1 30 | usage 1 31 | fi 32 | shift 33 | ;; 34 | esac 35 | done 36 | 37 | # initialize the local repository 38 | if [ -z "$CMSSW_BASE" ]; then 39 | echo "CMSSW environment not setup, please run 'cmsenv' before 'git cms-fetch-pr'." 40 | exit 1 41 | fi 42 | if ! [ -d "$CMSSW_BASE"/src/.git ]; then 43 | cd $CMSSW_BASE/src 44 | git cms-init --upstream-only 45 | fi 46 | 47 | if [[ $PULL =~ .*:.* ]]; then 48 | USER=$(echo "$PULL" | cut -d: -f1) 49 | PULL=$(echo "$PULL" | cut -d: -f2) 50 | else 51 | USER="cms-sw" 52 | fi 53 | 54 | REMOTE="git@github.com:$USER/cmssw.git" 55 | 56 | if [ -z "$BRANCH"]; then 57 | BRANCH="pull/$PULL" 58 | fi 59 | 60 | cd $CMSSW_BASE/src 61 | git fetch -n $REMOTE refs/pull/$PULL/head:$BRANCH 62 | -------------------------------------------------------------------------------- /git-cms-import-tagset: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from optparse import OptionParser 3 | from commands import getstatusoutput 4 | from sys import exit 5 | 6 | def format(s, **kwds): 7 | return s.encode(errors="ignore") % kwds 8 | 9 | def die(*out): 10 | for x in out: 11 | print x 12 | exit(1) 13 | 14 | if __name__ == "__main__": 15 | parser = OptionParser() 16 | parser.add_option("-n", "--dry-run", help="Do not do it but just print out the commit", dest="dryRun", action="store_true", default=False) 17 | parser.add_option("-d", "--dependency", help="Specify tagset dependency", dest="dependencies", default=None) 18 | parser.add_option("-m", "--merge", help="Do merge", dest="merge", default=False, action="store_true") 19 | parser.add_option("-s", "--strategy", help="Strategy to be used for the merge", dest="strategy", default="") 20 | parser.add_option("-X", "--strategy-option", help="Strategy to be used for the merge", dest="strategyOption", default="") 21 | opts, args = parser.parse_args() 22 | if not len(args): 23 | parser.error("Please specify at least one tagset ID") 24 | 25 | if opts.strategy: 26 | opts.strategy = "-s " + opts.strategy 27 | if opts.strategyOption: 28 | opts.strategyOption = "-X " + opts.strategyOption 29 | if opts.merge: 30 | opts.merge = "-m" 31 | else: 32 | opts.merge = "" 33 | 34 | for tagset in args: 35 | err, out = getstatusoutput("cmstc tagset %s" % tagset) 36 | pairs = [[y for y in x.split(" ") if y] for x in out.strip().split("\n")] 37 | print pairs 38 | getstatusoutput("rm -rf $CMSSW_BASE/src") 39 | for (pkg, tag) in pairs: 40 | print pkg, tag 41 | err, out = getstatusoutput(format("set -e ; git cms-addpkg %(pkg)s; cd $CMSSW_BASE/src; cvs rdiff -r CMSSW_6_2_0_pre8 -r %(tag)s %(pkg)s | patch -p1", 42 | pkg=pkg, 43 | tag=tag)) 44 | if err: 45 | die("Error while executing command", out) 46 | print out 47 | err, out = getstatusoutput(format("set -e ; cd $CMSSW_BASE/src ; git add -A . ; git commit -m \"`cmstc tagsetinfo %(tagset)s | grep -A100 -e'Description:' | grep -v -e '^Description:'`\"", 48 | tagset=tagset)) 49 | if err: 50 | die("Error while creating commit", out) 51 | if not opts.dependencies: 52 | err, out = getstatusoutput(format("set -e ; cd $CMSSW_BASE/src ; git rebase official-cmssw/CMSSW_7_0_X", 53 | tagset=tagset)) 54 | else: 55 | for dep in opts.dependencies.split(","): 56 | command = format("set -e ; cd $CMSSW_BASE/src ; git fetch my-cmssw tagset-%(tagset)s:my-cmssw/tagset-%(tagset)s; git rebase %(merge)s %(strategy)s %(strategyOption)s my-cmssw/tagset-%(tagset)s", 57 | tagset=dep, 58 | strategy=opts.strategy, 59 | strategyOption=opts.strategyOption, 60 | merge=opts.merge) 61 | print command 62 | err, out = getstatusoutput(command) 63 | if err: 64 | die("Error while rebasing", out) 65 | print out 66 | if opts.dryRun: 67 | err, out = getstatusoutput("cd $CMSSW_BASE/src ; git show") 68 | if err: 69 | die("Error while doing git show", out) 70 | print out 71 | exit(0) 72 | err, out = getstatusoutput(format("cd $CMSSW_BASE/src ; git push my-cmssw -f HEAD:tagset-%s" % tagset)) 73 | if err: 74 | die("Error while pushing to your repository", out) 75 | print out 76 | -------------------------------------------------------------------------------- /git-cms-init: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | # Initialises a local git repository for use with the official cmssw github remote and the user's github remote repositories 3 | 4 | case `uname` in 5 | Darwin) 6 | ECHO="echo" ;; 7 | *) 8 | ECHO="echo -e" ;; 9 | esac 10 | 11 | usage () { 12 | $ECHO "git cms-init [options] [release]" 13 | $ECHO 14 | $ECHO "Options:" 15 | $ECHO " -h \tthis help message" 16 | $ECHO 17 | $ECHO " -d, --debug \tenable debug output" 18 | $ECHO " --check \trun additional checks on the status of the user repository" 19 | $ECHO " --https \tuse https, rather than ssh to access your personal repository" 20 | $ECHO " --ssh \tuse ssh, rather than https to access the official repository" 21 | $ECHO " --upstream-only \tconfigure only the official upstream repository, not the user repository" 22 | $ECHO " -w, --enable-push \tenable pushing to the official upstream repository" 23 | $ECHO " -x, --extra NAME \tconfigure an additional repository at https://github.com/NAME/cmssw with pushing disabled" 24 | $ECHO " -X, --extra-push NAME\tconfigure an additional repository at https://github.com/NAME/cmssw with pushing enabled" 25 | $ECHO " -q, --quiet, -z \tdo not print out progress" 26 | $ECHO " -y, --yes \tassume yes to all questions" 27 | 28 | exit $1 29 | } 30 | 31 | # get default protocol from git config, or use "mixed" by default 32 | PROTOCOL=$(git config --get cms.protocol || echo mixed) 33 | if [ "$PROTOCOL" != "https" ] && [ "$PROTOCOL" != "ssh" ] && [ "$PROTOCOL" != "mixed" ]; then 34 | $ECHO "Unsupported value $PROTOCOL in cms.protocol (choose https, ssh, mixed)" 35 | exit 1 36 | fi 37 | 38 | # configuration 39 | CHECK= 40 | CUSTOM_REMOTE=false 41 | DEBUG=false 42 | VERBOSE=true 43 | UPSTREAM_ONLY=false 44 | UPSTREAM_PUSH=false 45 | EXTRAS= 46 | EXTRAS_PUSH= 47 | OAUTH_TOKEN="$(echo YmRjNTIxODVjOTVlOTA2Y2UxMzhlY2E5NTczNGU2ZTFlNjY5YTM0Ngo= | base64 --decode)" 48 | PROXY=`git config http.proxy` && PROXY="-x $PROXY" 49 | 50 | # colors and formatting 51 | RED='\033[31m' 52 | NORMAL='\033[0m' 53 | 54 | debug() { 55 | if $DEBUG; then 56 | $ECHO "$@" 57 | fi 58 | } 59 | 60 | verbose() { 61 | if $VERBOSE; then 62 | $ECHO "$@" 63 | fi 64 | } 65 | 66 | CMSSW_TAG= 67 | while [ "$#" != 0 ]; do 68 | case "$1" in 69 | -h | --help ) 70 | usage 0;; 71 | --check ) 72 | shift; CHECK=true ;; 73 | -d | --debug ) 74 | shift; set -x; DEBUG=true ;; 75 | -q | --quiet | -z ) 76 | shift; set +x; DEBUG=false; VERBOSE=false ;; 77 | -y | --yes ) 78 | shift; ASSUME_YES=1 ;; 79 | --https ) 80 | shift; PROTOCOL=https ;; 81 | --ssh ) 82 | shift; PROTOCOL=ssh ;; 83 | -w | --enable-push ) 84 | shift; UPSTREAM_PUSH=true ;; 85 | --upstream-only ) 86 | shift; UPSTREAM_ONLY=true ;; 87 | -x | --extra ) 88 | [ "$2" ] || { $ECHO "git cms-init: missing argument to option $1"; $ECHO; usage 1; } 89 | EXTRAS="$EXTRAS $2" 90 | shift 2 ;; 91 | -X | --extra-push ) 92 | [ "$2" ] || { $ECHO "git cms-init: missing argument to option $1"; $ECHO; usage 1; } 93 | EXTRAS_PUSH="$EXTRAS_PUSH $2" 94 | shift 2 ;; 95 | -*) 96 | $ECHO "git cms-init: unknown option $1"; $ECHO; usage 1 ;; 97 | *) 98 | if ! [ "$CMSSW_TAG" ]; then 99 | CMSSW_TAG=$1 100 | else 101 | $ECHO "git cms-init: unexpected argument $1" 102 | $ECHO 103 | usage 1 104 | fi 105 | shift 1 106 | ;; 107 | esac 108 | done 109 | 110 | BASH_FULL_VERSION=$((${BASH_VERSINFO[0]} * 10000 + ${BASH_VERSINFO[1]} * 100 + ${BASH_VERSINFO[2]})) 111 | if (( BASH_FULL_VERSION >= 40100 )); then 112 | # bash 4.1 or newer 113 | if $VERBOSE; then 114 | # send verbose messages to stderr 115 | exec {verbose}>&2 116 | else 117 | # send verbose messages to /dev/null 118 | exec {verbose}> /dev/null 119 | fi 120 | if $DEBUG; then 121 | # send debug messages to stderr 122 | exec {debug}>&2 123 | else 124 | # send debug messages to /dev/null 125 | exec {debug}> /dev/null 126 | fi 127 | else 128 | # bash 4.0 or older 129 | verbose=11 130 | if $VERBOSE; then 131 | # send verbose messages to stderr 132 | exec 11>&2 133 | else 134 | # send verbose messages to /dev/null 135 | exec 11> /dev/null 136 | fi 137 | debug=12 138 | if $DEBUG; then 139 | # send debug messages to stderr 140 | exec 12>&2 141 | else 142 | # send debug messages to /dev/null 143 | exec 12> /dev/null 144 | fi 145 | fi 146 | 147 | if ! $UPSTREAM_ONLY; then 148 | # check the user details in the git configuration 149 | USER_FULLNAME="`git config --global --get user.name || true`" 150 | USER_EMAIL="`git config --global --get user.email || true`" 151 | GITHUB_USERNAME="`git config --global --get user.github || true`" 152 | if [ -z "$GITHUB_USERNAME" ] || [ -z "$USER_FULLNAME" ] || [ -z "$USER_EMAIL" ]; then 153 | $ECHO "Cannot find your details in the git configuration." 154 | if [ "X$USER_FULLNAME" = X ]; then 155 | $ECHO 156 | $ECHO "Please set up your full name via:" 157 | $ECHO 158 | $ECHO " git config --global user.name ' '" 159 | $ECHO 160 | fi 161 | if [ "X$USER_EMAIL" = X ]; then 162 | $ECHO 163 | $ECHO "Please set up your email via:" 164 | $ECHO 165 | $ECHO " git config --global user.email ''" 166 | $ECHO 167 | fi 168 | if [ "X$GITHUB_USERNAME" = X ]; then 169 | $ECHO 170 | $ECHO "Please set up your GitHub user name via:" 171 | $ECHO 172 | $ECHO " git config --global user.github " 173 | $ECHO 174 | fi 175 | exit 1 176 | fi 177 | fi 178 | 179 | if [ "X$CMSSW_BASE" = X ]; then 180 | if [ "X$CMSSW_TAG" = X ]; then 181 | verbose "CMSSW environment not setup. Do cmsenv in some workarea or specify tag to checkout." 182 | exit 1 183 | else 184 | verbose "Warning CMSSW environment not found. Checking out packages in $PWD/src." 185 | CMSSW_BASE=$PWD 186 | fi 187 | fi 188 | 189 | if [ -d $CMSSW_BASE/src/.git ]; then 190 | CURRENT_BRANCH=`git --git-dir=$CMSSW_BASE/src/.git symbolic-ref --short HEAD` 191 | CURRENT_TAG=`echo $CURRENT_BRANCH | sed -e's/^from-*//'` 192 | fi 193 | 194 | if [ "X$CMSSW_TAG" = X ]; then 195 | if [ "$CURRENT_BRANCH" ]; then 196 | debug "No release tags specified, using current branch $CURRENT_BRANCH." 197 | CMSSW_TAG=$CURRENT_TAG 198 | elif [ "$CMSSW_GIT_HASH" ]; then 199 | debug "No release tags specified, using default $CMSSW_GIT_HASH." 200 | CMSSW_TAG=$CMSSW_GIT_HASH 201 | else 202 | debug "No release tags specified, using default $CMSSW_VERSION." 203 | CMSSW_TAG=$CMSSW_VERSION 204 | fi 205 | fi 206 | 207 | if [ "$CURRENT_BRANCH" ] && [ "$CURRENT_TAG" != "$CMSSW_TAG" ]; then 208 | $ECHO "Attention: you have requested a release tag $CMSSW_TAG, but your local git repository has been set up for $CURRENT_TAG." 209 | $ECHO "Aborting." 210 | exit 1 211 | fi 212 | 213 | CMSSW_BASE_BRANCH=`echo $CMSSW_TAG | sed -e 's/\(CMSSW_[0-9][0-9]*_[0-9][0-9]*\).*/\1/'` 214 | 215 | # SLHC releases 216 | case $CMSSW_TAG in 217 | *_SLHC*) 218 | CMSSW_BRANCH=${CMSSW_BASE_BRANCH}_X_SLHC ;; 219 | *) 220 | CMSSW_BRANCH=${CMSSW_BASE_BRANCH}_X ;; 221 | esac 222 | 223 | # This is not the case at FNAL. Disabling it for now. 224 | #IN_RELEASE=`echo $PWD | grep -q -e "^$CMSSW_BASE" 2> /dev/null && echo 1 || echo 0` 225 | #if [ "X$IN_RELEASE" = X0 ]; then 226 | # OLD_CMSSW_BASE=$CMSSW_BASE 227 | # eval `scram run -sh` >/dev/null 228 | # IN_RELEASE=`echo $PWD | grep -q -e "^$CMSSW_BASE" 2> /dev/null && echo 1 || echo 0` 229 | # if [ "X$IN_RELEASE" = X0 ]; then 230 | # $ECHO git cms-addpkg must be run from inside a CMSSW area. 231 | # exit 1 232 | # else 233 | # $ECHO Error: You have currently set up the environment of $OLD_CMSSW_BASE, however you are running inside $CMSSW_BASE. 234 | # $ECHO Please go inside $OLD_CMSSW_BASE, or use cmsenv to switch to $CMSSW_BASE. 235 | # exit 1 236 | # fi 237 | #fi 238 | 239 | case `git --version` in 240 | git\ version\ 1.7*) 241 | # make the reference checkout work on git 1.7.x (see commit d5ed1e3aa81f22f993c19073321ee65d2c46c0c5 to git-cms-addpkg) 242 | PROTOCOL=ssh 243 | # git 1.7.x does not support a leading slash in .gitignore and .git/info/sparse-checkout 244 | LEADING_SLASH= 245 | ;; 246 | *) 247 | LEADING_SLASH=/ 248 | ;; 249 | esac 250 | 251 | # check if we can access GitHub over https 252 | if [ "$PROTOCOL" != "ssh" ] && ! curl -L -s $PROXY -H "Authorization: token $OAUTH_TOKEN" "https://api.github.com/meta" > /dev/null; then 253 | if [ "$PROTOCOL" = "https" ]; then 254 | # unable to contact GitHub over https, aborting 255 | verbose "Attention: git is unable to access GitHub over https, aborting." 256 | verbose "You may want to retry with the --ssh option." 257 | exit 1 258 | else 259 | # unable to contact GitHub over https, switching to ssh 260 | verbose "Attention: git is unable to access GitHub over https, switching to ssh." 261 | PROTOCOL=ssh 262 | OFFICIAL_CMSSW_REPO="git@github.com:cms-sw/cmssw.git" 263 | fi 264 | fi 265 | 266 | if [ "$PROTOCOL" = "ssh" ]; then 267 | OFFICIAL_CMSSW_REPO=git@github.com:cms-sw/cmssw.git 268 | USER_CMSSW_REPO=git@github.com:$GITHUB_USERNAME/cmssw.git 269 | elif [ "$PROTOCOL" = "https" ]; then 270 | OFFICIAL_CMSSW_REPO=https://github.com/cms-sw/cmssw.git 271 | USER_CMSSW_REPO=https://github.com/$GITHUB_USERNAME/cmssw.git 272 | elif [ "$PROTOCOL" = "mixed" ]; then 273 | OFFICIAL_CMSSW_REPO=https://github.com/cms-sw/cmssw.git 274 | USER_CMSSW_REPO=https://github.com/$GITHUB_USERNAME/cmssw.git 275 | USER_CMSSW_REPO_PUSH=git@github.com:$GITHUB_USERNAME/cmssw.git 276 | fi 277 | 278 | # check if a shared reference repository is available, otherwise set up a personal one 279 | if [ "$CMSSW_GIT_REFERENCE" = "" ]; then 280 | if [ -e /cvmfs/cms-ib.cern.ch/git/cms-sw/cmssw.git ] ; then 281 | CMSSW_GIT_REFERENCE=/cvmfs/cms-ib.cern.ch/git/cms-sw/cmssw.git 282 | elif [ -e /cvmfs/cms.cern.ch/cmssw.git.daily ] ; then 283 | CMSSW_GIT_REFERENCE=/cvmfs/cms.cern.ch/cmssw.git.daily 284 | else 285 | CMSSW_GIT_REFERENCE=~/.cmsgit-cache 286 | fi 287 | fi 288 | 289 | if [ ! -e $CMSSW_GIT_REFERENCE ]; then 290 | while [ X$QUESTION_DONE = X ]; do 291 | if [ X$ASSUME_YES = X ]; then 292 | read -n 1 -p "Your reference git repository does not seem to exist, would you like to create it? [ y / N / ? ] " 293 | echo 294 | QUESTION_DONE=1 295 | else 296 | REPLY=y 297 | QUESTION_DONE=1 298 | fi 299 | case $REPLY in 300 | y|Y) 301 | git clone --bare $OFFICIAL_CMSSW_REPO $CMSSW_GIT_REFERENCE 302 | touch $CMSSW_GIT_REFERENCE/create-`whoami` 303 | ;; 304 | [?]) 305 | $ECHO 306 | $ECHO Answering yes will create a new cache directory in \$CMSSW_GIT_REFERENCE: 307 | $ECHO 308 | $ECHO i.e. $CMSSW_GIT_REFERENCE 309 | $ECHO 310 | $ECHO and put there a copy of the official CMSSW repository. git cms-addpkg will then 311 | $ECHO reuse this information to keep your CMSSW workareas to a minimal size. 312 | $ECHO The initial checkout could take a few minutes, but all the others should then 313 | $ECHO take only a few seconds. 314 | $ECHO 315 | $ECHO Just say yes. 316 | $ECHO 317 | QUESTION_DONE= 318 | ;; 319 | *) 320 | CMSSW_GIT_REFERENCE= 321 | ;; 322 | esac 323 | done 324 | fi 325 | 326 | # if using a personal reference repository, update it from the official one 327 | if [ -e $CMSSW_GIT_REFERENCE/create-`whoami` ]; then 328 | (cd $CMSSW_GIT_REFERENCE ; git remote update origin >&${verbose} 2>&1) 329 | fi 330 | 331 | [ -e $CMSSW_BASE/src ] || mkdir $CMSSW_BASE/src 332 | cd $CMSSW_BASE/src 333 | 334 | # setup the upstream "official" repository 335 | if [ ! -d "$CMSSW_BASE/src/.git" ]; then 336 | # clone the official repository from $OFFICIAL_CMSSW_REPO, using $CMSSW_GIT_REFERENCE as a local reference, inside $CMSSW_BASE/src 337 | # name the remote repository "official-cmssw" 338 | # start on the branch $CMSSW_BRANCH 339 | # do not checkout any files 340 | # import all remote tags 341 | if [ "$CMSSW_GIT_REFERENCE" ]; then 342 | git clone --branch $CMSSW_BRANCH --no-checkout --reference $CMSSW_GIT_REFERENCE --origin official-cmssw $OFFICIAL_CMSSW_REPO $CMSSW_BASE/src >&${verbose} 2>&1 343 | else 344 | git clone --branch $CMSSW_BRANCH --no-checkout --origin official-cmssw $OFFICIAL_CMSSW_REPO $CMSSW_BASE/src >&${verbose} 2>&1 345 | fi 346 | 347 | if ! $UPSTREAM_PUSH; then 348 | # disable pushing to the official upstream repository 349 | git remote set-url --push official-cmssw disabled 350 | fi 351 | 352 | # update all branches and tags from the upstream repository 353 | git fetch official-cmssw --tags 2>&${verbose} 354 | 355 | # setup sparse checkout 356 | git config core.sparsecheckout true 357 | { 358 | echo "${LEADING_SLASH}.gitignore" 359 | echo "${LEADING_SLASH}.clang-tidy" 360 | echo "${LEADING_SLASH}.clang-format" 361 | } > $CMSSW_BASE/src/.git/info/sparse-checkout 362 | git read-tree -mu HEAD 363 | 364 | # set up extra read-only repositories 365 | for EXTRA in $EXTRAS; do 366 | if [ "$PROTOCOL" = "ssh" ]; then 367 | git remote add $EXTRA git@github.com:$EXTRA/cmssw.git 368 | elif [ "$PROTOCOL" = "https" ]; then 369 | git remote add $EXTRA https://github.com/$EXTRA/cmssw.git 370 | elif [ "$PROTOCOL" = "mixed" ]; then 371 | git remote add $EXTRA https://github.com/$EXTRA/cmssw.git 372 | fi 373 | git remote set-url --push $EXTRA disabled 374 | git fetch $EXTRA 375 | done 376 | 377 | # set up extra read-write repositories 378 | for EXTRA in $EXTRAS_PUSH; do 379 | if [ "$PROTOCOL" = "ssh" ]; then 380 | git remote add $EXTRA git@github.com:$EXTRA/cmssw.git 381 | elif [ "$PROTOCOL" = "https" ]; then 382 | git remote add $EXTRA https://github.com/$EXTRA/cmssw.git 383 | elif [ "$PROTOCOL" = "mixed" ]; then 384 | git remote add $EXTRA https://github.com/$EXTRA/cmssw.git 385 | git remote set-url --push $EXTRA git@github.com:$EXTRA/cmssw.git 386 | fi 387 | git fetch $EXTRA 388 | done 389 | 390 | # create a new branch, pointing to the commit corresponding to $CMSSW_TAG, and switch to it 391 | git checkout $CMSSW_TAG -b from-$CMSSW_TAG 2>&${verbose} 392 | else 393 | # update all branches and tags from the upstream repository 394 | git fetch official-cmssw --tags 2>&${verbose} 395 | fi 396 | 397 | # setup the user's repository, if it doesn't exist already 398 | if ! $UPSTREAM_ONLY && ! git remote | grep my-cmssw -q; then 399 | 400 | # check if the user has explicitly configured a remote repository 401 | if git config remote.my-cmssw.url >& /dev/null; then 402 | CUSTOM_REMOTE=true 403 | USER_CMSSW_REPO=`git config remote.my-cmssw.url` 404 | USER_CMSSW_REPO_PUSH=`git config remote.my-cmssw.pushurl` 405 | verbose "Attention: using the 'my-cmssw' remote from your git configuration: $RED$USER_CMSSW_REPO$NORMAL" 406 | verbose "" 407 | fi 408 | 409 | # check if the user repository is accessible 410 | if $CUSTOM_REMOTE || [ "$PROTOCOL" = "ssh" ]; then 411 | if [ "$CHECK" ] && ! git ls-remote $USER_CMSSW_REPO >&${debug} 2>&1; then 412 | verbose "Attention: git is unable to access your 'my-cmssw' remote repository ($RED$USER_CMSSW_REPO$NORMAL). " 413 | verbose "You can work locally, but you will not be able to push your changes to it." 414 | verbose "" 415 | USER_CMSSW_REPO="" 416 | fi 417 | else 418 | # check the user setup on GitHub 419 | if curl -L -s $PROXY -H "Authorization: token $OAUTH_TOKEN" "https://api.github.com/users/$GITHUB_USERNAME" | tee >(cat >&${debug}) | grep -q -i 'Not Found' ; then 420 | verbose "You don't seem to have a GitHub accout, or your GitHub username ($RED$GITHUB_USERNAME$NORMAL) is not correct." 421 | verbose "($RED$GITHUB_USERNAME$NORMAL) is not correct." 422 | verbose "You can work locally, but you will not be able to push your changes to GitHub for inclusion " 423 | verbose "in the official CMSSW distribution." 424 | verbose "" 425 | verbose "You can correct your GitHub user name via:" 426 | verbose "" 427 | verbose " git config --global user.github " 428 | verbose "" 429 | verbose "" 430 | verbose "To create a personal repository:" 431 | verbose " visit to https://github.com/ and register a new account" 432 | verbose " visit to https://github.com/cms-sw/cmssw and click on the Fork button" 433 | verbose " select the option to fork the repository under your username ($RED$GITHUB_USERNAME$NORMAL)" 434 | verbose "" 435 | USER_CMSSW_REPO="" 436 | elif ! curl -L -s $PROXY -H "Authorization: token $OAUTH_TOKEN" "https://api.github.com/users/$GITHUB_USERNAME/repos" | tee >(cat >&${debug}) | grep -q '"name": *"cmssw"'; then 437 | verbose "You don't seem to have a personal repository, or your GitHub username ($RED$GITHUB_USERNAME$NORMAL) is not correct." 438 | verbose "You can work locally, but you will not be able to push your changes to GitHub for inclusion " 439 | verbose "in the official CMSSW distribution." 440 | verbose "" 441 | verbose "You can correct your GitHub user name via:" 442 | verbose "" 443 | verbose " git config --global user.github " 444 | verbose "" 445 | verbose "" 446 | verbose "To create a personal repository:" 447 | verbose " - go to https://github.com/ and log in" 448 | verbose " - go to https://github.com/cms-sw/cmssw and click on the Fork button" 449 | verbose " - select the option to fork the repository under your username ($RED$GITHUB_USERNAME$NORMAL)" 450 | verbose "" 451 | USER_CMSSW_REPO="" 452 | elif [ "$CHECK" ] && ! git ls-remote $USER_CMSSW_REPO >&${debug} 2>&1; then 453 | verbose "Attention: your GitHub account ($RED$GITHUB_USERNAME$NORMAL) and personal repository ($RED$USER_CMSSW_REPO$NORMAL) " 454 | verbose "are properly configured, but git is unable to access it." 455 | verbose "You can work locally, but you will not be able to push your changes to GitHub for inclusion " 456 | verbose "in the official CMSSW distribution." 457 | verbose "" 458 | USER_CMSSW_REPO="" 459 | fi 460 | fi 461 | 462 | if [ "$USER_CMSSW_REPO" ]; then 463 | # add the user's remote repository 464 | git remote add my-cmssw $USER_CMSSW_REPO 465 | [ "$USER_CMSSW_REPO_PUSH" ] && git remote set-url --push my-cmssw $USER_CMSSW_REPO_PUSH 466 | git fetch my-cmssw 2>&${verbose} 467 | fi 468 | fi 469 | 470 | # avoid asking for password for 24 hours. 471 | GIT_CREDENTIAL_CACHE="`git config --get credential.cache || true`" 472 | if [ "X$GIT_CREDENTIAL_CACHE" = X ]; then 473 | case `uname` in 474 | Darwin*) git config --add credential.cache osxkeychain ;; 475 | Linux*) git config --add credential.cache "cache --timeout=86400 --socket $TMPDIR/.git-credential-cache-socket" ;; 476 | esac 477 | fi 478 | 479 | debug "You are on branch `git symbolic-ref --short HEAD`" 480 | -------------------------------------------------------------------------------- /git-cms-merge-topic: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | case `uname` in 4 | Linux) ECHO="echo -e" ;; 5 | *) ECHO="echo" ;; 6 | esac 7 | 8 | check_command(){ 9 | declare -A ARG_INDICES 10 | ARG_INDICES["cms-merge-topic"]="0 1 2 3 4 5 6 7 8 10" 11 | ARG_INDICES["cms-rebase-topic"]="0 1 2 3 4 5 6 8 9 10" 12 | ARG_INDICES["cms-checkout-topic"]="0 1 2 8 10" 13 | ARG_INDICES["cms-squash-topic"]="0 1 2 3 4 8 10 11 12" 14 | 15 | COMMAND_TO_CHECK=$1 16 | IND_TO_CHECK=$2 17 | OPTNAME=$3 18 | if [ -z "$IND_TO_CHECK" ]; then 19 | echo "${ARG_INDICES[$COMMAND_TO_CHECK]}" 20 | # check if index is in allowed list 21 | elif [[ " ${ARG_INDICES[$COMMAND_TO_CHECK]} " =~ " ${IND_TO_CHECK} " ]]; then 22 | return 0 23 | else 24 | $ECHO "Unsupported option $OPTNAME" 25 | exit 1 26 | fi 27 | } 28 | 29 | usage() { 30 | COMMAND_NAME=$1 31 | CODE=$2 32 | POS_ARG="[:]{|}" 33 | # positional arg is not required for squash 34 | if [ "$COMMAND_NAME" = "cms-squash-topic" ]; then 35 | POS_ARG="[$POS_ARG]" 36 | fi 37 | $ECHO "git $COMMAND_NAME [options] $POS_ARG" 38 | $ECHO 39 | $ECHO "Options:" 40 | $ECHO "-h, --help \tthis help message" 41 | $ECHO 42 | 43 | ARGS=() 44 | ARGS[0]="-d, --debug \tenable debug output" 45 | ARGS[1]=" --https \taccess GitHub over https (default)" 46 | ARGS[2]=" --ssh \taccess GitHub over ssh" 47 | ARGS[3]=" --no-backup \tdon't create backup branch" 48 | ARGS[4]=" --backup-name \tspecify suffix for backup branch (default = _backup)" 49 | ARGS[5]="-s, --strategy \tspecify strategy when merging" 50 | ARGS[6]="-X, --strategy-option \tspecify strategy option when merging" 51 | ARGS[7]=" --no-commit \tdo not do the final commit when merging" 52 | ARGS[8]="-o, --old-base \tspecify old base for merge-base or rebase (not used by default)" 53 | ARGS[9]="-n, --new-base \tspecify new base for rebase (default = current branch)" 54 | ARGS[10]="-u, --unsafe \tdo not perform checkdeps at the end\n \t(default: header, python)" 55 | ARGS[11]=" --current \tsquash the current branch" 56 | ARGS[12]="-m, --message \tspecify new message for squashed commit (instead of using prepopulated message from original commits)" 57 | 58 | for IND in $(check_command $COMMAND_NAME); do 59 | $ECHO "${ARGS[$IND]}" 60 | done 61 | 62 | exit $CODE 63 | } 64 | 65 | # colors and formatting 66 | RED='\033[31m' 67 | NORMAL='\033[0m' 68 | 69 | # get default protocol from git config, or use "mixed" by default 70 | PROTOCOL=$(git config --get cms.protocol || echo mixed) 71 | if [ "$PROTOCOL" != "https" ] && [ "$PROTOCOL" != "ssh" ] && [ "$PROTOCOL" != "mixed" ]; then 72 | $ECHO "Unsupported value $PROTOCOL in cms.protocol (choose https, ssh, mixed)" 73 | exit 1 74 | fi 75 | 76 | DEBUG=0 77 | INITOPTIONS="" # options passed to git cms-init 78 | BACKUP=true 79 | BACKUP_NAME=_backup 80 | 81 | COMMAND_NAME=$(basename $0 | sed -e's/^git-//') 82 | if [ "$COMMAND_NAME" != "cms-merge-topic" ]; then 83 | NOMERGE=true 84 | else 85 | INITOPTIONS="--upstream-only" 86 | fi 87 | 88 | while [ $# -gt 0 ]; do 89 | case $1 in 90 | # for backward compatibility (now default) 91 | -A|--all-deps) 92 | shift 93 | ;; 94 | # "hidden" option to pass to git cms-init 95 | -q|--quiet|-z) 96 | INITOPTIONS="$INITOPTIONS $1" 97 | DEBUG=0 98 | shift 99 | ;; 100 | # preserving order from usage() 101 | -d|--debug) 102 | check_command $COMMAND_NAME 0 $1 103 | INITOPTIONS="$INITOPTIONS $1" 104 | DEBUG=1 105 | shift 106 | ;; 107 | --https ) 108 | check_command $COMMAND_NAME 1 $1 109 | INITOPTIONS="$INITOPTIONS $1" 110 | PROTOCOL=https 111 | shift 112 | ;; 113 | --ssh ) 114 | check_command $COMMAND_NAME 2 $1 115 | INITOPTIONS="$INITOPTIONS $1" 116 | PROTOCOL=ssh 117 | shift 118 | ;; 119 | --no-backup ) 120 | check_command $COMMAND_NAME 3 $1 121 | BACKUP="" 122 | shift 123 | ;; 124 | --backup-name ) 125 | check_command $COMMAND_NAME 4 $1 126 | BACKUP_NAME=$2 127 | shift; shift 128 | ;; 129 | -s | --strategy ) 130 | check_command $COMMAND_NAME 5 $1 131 | MERGE_STRATEGY="-s $2" 132 | shift; shift 133 | ;; 134 | -X | --strategy-option ) 135 | check_command $COMMAND_NAME 6 $1 136 | STRATEGY_OPTION="-X $2" 137 | shift; shift 138 | ;; 139 | --no-commit ) 140 | check_command $COMMAND_NAME 7 $1 141 | NO_COMMIT=--no-commit 142 | shift 143 | ;; 144 | -o | --old-base ) 145 | check_command $COMMAND_NAME 8 $1 146 | OLD_BASE=$2 147 | shift; shift 148 | ;; 149 | -n | --new-base ) 150 | check_command $COMMAND_NAME 9 $1 151 | NEW_BASE=$2 152 | shift; shift 153 | ;; 154 | -u|--unsafe) 155 | check_command $COMMAND_NAME 10 $1 156 | UNSAFE=true 157 | shift 158 | ;; 159 | --current ) 160 | check_command $COMMAND_NAME 11 $1 161 | # settings related to using current branch for squash 162 | BRANCH=$(git rev-parse --abbrev-ref HEAD) 163 | LOCAL_BRANCH="$BRANCH" 164 | BRANCH_DEFAULTED=true 165 | UNSAFE=true 166 | shift 167 | ;; 168 | -m | --message ) 169 | check_command $COMMAND_NAME 12 $1 170 | MESSAGE=$2 171 | shift; shift 172 | ;; 173 | -h|--help) 174 | usage $COMMAND_NAME 0;; 175 | -*) 176 | echo "Unknown option $1" ; exit 1 ;; 177 | *) 178 | if [ ! X$BRANCH = X ]; then 179 | echo "Unexpected extra argument $1" ; exit 1 180 | fi 181 | # Handle branch options: 182 | # 183 | # - Generic personal branch or pull request: `:|` 184 | # - Generic cms-sw branch: `` 185 | # - Pull request: `` 186 | GITHUB_USER=cms-sw 187 | BRANCH=$1 188 | LOCAL_BRANCH=$1 189 | # if the branch contains a colon, split the first part to be the github user 190 | if [[ $BRANCH =~ ^.+:.+$ ]]; then 191 | GITHUB_USER=`echo $BRANCH | cut -f1 -d:` 192 | BRANCH=`echo $BRANCH | cut -f2 -d:` 193 | LOCAL_BRANCH=$BRANCH 194 | fi 195 | # if the branch is a number, assume it to be a pull request 196 | if [[ $BRANCH =~ ^[0-9]+$ ]]; then 197 | PULL=$BRANCH 198 | BRANCH=refs/pull/$PULL/head 199 | LOCAL_BRANCH=pull/$PULL 200 | fi 201 | shift 202 | ;; 203 | esac 204 | done 205 | if [ "$BRANCH" == "" ]; then 206 | usage $COMMAND_NAME 1 207 | fi 208 | 209 | BASH_FULL_VERSION=$((${BASH_VERSINFO[0]} * 10000 + ${BASH_VERSINFO[1]} * 100 + ${BASH_VERSINFO[2]})) 210 | if (( BASH_FULL_VERSION >= 40100 )); then 211 | # bash 4.1 or newer 212 | if [ $DEBUG == 0 ]; then 213 | # send debug messages to /dev/null 214 | exec {debug}> /dev/null 215 | else 216 | # send debug messages to stderr 217 | exec {debug}>&2 218 | # pass the debug option to subcommands 219 | DEBUG_OPT=-d 220 | # enable shell tracing 221 | set -x 222 | fi 223 | else 224 | # bash 4.0 or older 225 | debug=12 226 | if [ $DEBUG == 0 ]; then 227 | # send debug messages to /dev/null 228 | exec 12> /dev/null 229 | else 230 | # send debug messages to stderr 231 | exec 12>&2 232 | # pass the debug option to subcommands 233 | DEBUG_OPT=-d 234 | # enable shell tracing 235 | set -x 236 | fi 237 | fi 238 | 239 | TEMP_BRANCH_WORD=$(echo $COMMAND_NAME | cut -d'-' -f2) 240 | TEMP_BRANCH=${TEMP_BRANCH_WORD}-attempt 241 | 242 | # initialize the local repository 243 | if [ -z "$CMSSW_BASE" ]; then 244 | echo "CMSSW environment not setup, please run 'cmsenv' before 'git $COMMAND_NAME'." 245 | exit 1 246 | fi 247 | if ! [ -d $CMSSW_BASE/src/.git ]; then 248 | git cms-init $INITOPTIONS 249 | fi 250 | 251 | cd $CMSSW_BASE/src 252 | if [ -z "$NEW_BASE" ]; then 253 | NEW_BASE=$(git rev-parse --abbrev-ref HEAD) 254 | fi 255 | git fetch . +HEAD:$TEMP_BRANCH || { echo "You are on a failed $TEMP_BRANCH_WORD branch. Do \"git branch\" and checkout the one you were on."; exit 1; } 256 | 257 | if [ "$(git status --porcelain --untracked=no | grep '^[ACDMRU]')" ]; then 258 | $ECHO "${RED}Error:${NORMAL} there are staged but not committed changes on your working tree, please commit or stash them." 259 | exit 1 260 | fi 261 | 262 | if [ "$PROTOCOL" = "ssh" ]; then 263 | REPOSITORY=git@github.com:$GITHUB_USER/cmssw.git 264 | else 265 | REPOSITORY=https://github.com/$GITHUB_USER/cmssw.git 266 | fi 267 | 268 | FULL_BRANCH=$GITHUB_USER/$BRANCH 269 | # if squashing current branch, default base is CMSSW release 270 | if [ "$BRANCH_DEFAULTED" = "true" ]; then 271 | FULL_BRANCH=$BRANCH 272 | if [ -z "$OLD_BASE" ]; then 273 | OLD_BASE=$CMSSW_VERSION 274 | fi 275 | # temp branch will not be used 276 | TEMP_BRANCH= 277 | else 278 | # check if the "branch" is actually an annotated tag, and dereference it 279 | COMMIT=`git ls-remote -t $REPOSITORY $BRANCH^{} | cut -c -40` 280 | if [ -z "$COMMIT" ]; then 281 | COMMIT=$BRANCH 282 | fi 283 | 284 | # Fetch the branch specified from github and replace merge-attempt with it. 285 | # The + is used to force the merge-attempt branch to be updated. 286 | git fetch -n $REPOSITORY +$COMMIT:$FULL_BRANCH 287 | # Save the name of the current branch. 288 | CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD` 289 | # Attempt a merge in a separate branch 290 | git checkout $TEMP_BRANCH >&${debug} 291 | fi 292 | if [ -n "$OLD_BASE" ]; then 293 | MERGE_BASE_BRANCH=$OLD_BASE 294 | else 295 | MERGE_BASE_BRANCH=$CURRENT_BRANCH 296 | fi 297 | MERGE_BASE=`git merge-base $FULL_BRANCH $MERGE_BASE_BRANCH` 298 | if [ "$BRANCH_DEFAULTED" != "true" ]; then 299 | git cms-sparse-checkout $DEBUG_OPT $MERGE_BASE $FULL_BRANCH 300 | git read-tree -mu HEAD 301 | fi 302 | 303 | # optional backup (not for checkout-topic) 304 | if [ "$BACKUP" = "true" ] && [ "$COMMAND_NAME" != "cms-checkout-topic" ]; then 305 | git branch -f ${LOCAL_BRANCH}${BACKUP_NAME} $FULL_BRANCH 306 | fi 307 | 308 | # in no-merge case, just checkout a new branch 309 | if [ "$NOMERGE" = "true" ]; then 310 | if [ "$BRANCH_DEFAULTED" != "true" ]; then 311 | git checkout -B $LOCAL_BRANCH $FULL_BRANCH 312 | echo "Created branch $LOCAL_BRANCH to follow $BRANCH from repository $GITHUB_USER" 313 | fi 314 | # now try a rebase if desired 315 | if [ "$COMMAND_NAME" = "cms-rebase-topic" ]; then 316 | if [ -n "$OLD_BASE" ]; then 317 | $ECHO "git rebase $MERGE_STRATEGY $STRATEGY_OPTION --onto $NEW_BASE $OLD_BASE $LOCAL_BRANCH" 318 | git rebase $MERGE_STRATEGY $STRATEGY_OPTION --onto $NEW_BASE $OLD_BASE $LOCAL_BRANCH 319 | else 320 | git rebase $MERGE_STRATEGY $STRATEGY_OPTION $NEW_BASE $LOCAL_BRANCH 321 | fi 322 | # or a squash 323 | elif [ "$COMMAND_NAME" = "cms-squash-topic" ]; then 324 | # save the list of authors 325 | SQUASH_AUTHOR="$(git config --get user.name) <$(git config --get user.email)>" 326 | # git log w/ specified format prints: 327 | # Co-authored-by: Author 328 | # commit raw subject + body (which might also contain Co-authored-by lines, possibly indented) 329 | # sed -n suppresses printouts by default 330 | # then selects lines matching: any number of spaces + "Co-authored-by: " (which is then removed) 331 | # i = case-insensitive, p = print 332 | # finally, sort removes duplicates, and grep removes the current user (who will already be the author of the squash commit) 333 | readarray -t COAUTHORS < <(git log $MERGE_BASE_BRANCH..$FULL_BRANCH --format="Co-Authored-by: %an <%ae>%n%B" | sed -n 's/^ *Co-authored-by: //ip' | sort -u | grep -v "$SQUASH_AUTHOR") 334 | # by default, automatically populate commit message 335 | git reset --hard $MERGE_BASE 336 | git merge --squash "HEAD@{1}" 337 | if [ -n "$MESSAGE" ]; then 338 | git commit -m "$MESSAGE" 339 | else 340 | GIT_EDITOR=true git commit 341 | fi 342 | # amend to include extra authors 343 | if [ ${#COAUTHORS[@]} -gt 0 ]; then 344 | COAUTHOR_MESSAGE=$(printf 'Co-authored-by: %s\n' "${COAUTHORS[@]}") 345 | git commit --amend --message="$(git show --format=%B --no-patch HEAD)" --message="$COAUTHOR_MESSAGE" 346 | fi 347 | fi 348 | # otherwise, perform merge 349 | else 350 | git merge $NO_COMMIT $MERGE_STRATEGY $STRATEGY_OPTION --no-ff -m "Merged $BRANCH from repository $GITHUB_USER with cms-merge-topic" $GITHUB_USER/$BRANCH || { echo "Unable to merge branch $BRANCH from repository $GITHUB_USER." ; exit 1; } 351 | if [ ! X$NO_COMMIT = X ]; then 352 | echo \"--no-commit\" specified: not committing and leaving you on the $TEMP_BRANCH branch.\n Use git-status to check changes. ; exit 0 353 | fi 354 | git checkout $CURRENT_BRANCH 355 | # Add the missing files. 356 | git read-tree -mu HEAD 357 | # This should always be a FF commit. 358 | git merge --ff $TEMP_BRANCH >&${debug} 359 | fi 360 | # Delete the branch used for merge 361 | if [ -n "$TEMP_BRANCH" ]; then 362 | git branch -D $TEMP_BRANCH >&${debug} || true 363 | fi 364 | # Do checkdeps unless not specified. 365 | if [ ! "X$UNSAFE" = Xtrue ]; then 366 | git cms-checkdeps -a -A 367 | fi 368 | # check if topic branch is behind release branch 369 | if [ "$COMMAND_NAME" = "cms-checkout-topic" ] || ( [ "$COMMAND_NAME" = "cms-squash-topic" ] && [ "$BRANCH_DEFAULTED" != "true" ] ); then 370 | NBEHIND=$(git rev-list $LOCAL_BRANCH..$CURRENT_BRANCH | wc -l) 371 | if [ "$NBEHIND" -gt 0 ]; then 372 | $ECHO "Warning: $LOCAL_BRANCH is behind $CURRENT_BRANCH. You may not be able to compile or run." 373 | fi 374 | fi 375 | -------------------------------------------------------------------------------- /git-cms-rebase-topic: -------------------------------------------------------------------------------- 1 | git-cms-merge-topic -------------------------------------------------------------------------------- /git-cms-remote: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | function usage() { 4 | cat <<@EOF 5 | usage: git cms-remote add [--ssh|--https] [-w|--enable-push] USER 6 | 7 | Description: 8 | Adds a remote repository called USER pointing to https://github.com/USER/cmssw.git . 9 | By default only fetching from this remote is enabled, using the HTTPS protocol. 10 | The default behaviour is to immediately fetch the new remote repository; this can be 11 | disabled with the '--no-fetch' option. 12 | Pushing can be enabled with the '-w' or '--enable-push' option; the default is 13 | to use the SSH protocol. 14 | If '--ssh' is given, the SSH protocol will be used for all URLs. 15 | If '--https' is given, the HTTPS protocol will be used for all URLS. 16 | 17 | Options: 18 | -h|--help display this usage message 19 | --https use the HTTPS protocol for fetching and pushing 20 | --ssh use the SSH protocol for fetching and pushing 21 | --fetch automatically fetch the new remote (default) 22 | --no-fetch do not automatically fetch the new remote 23 | -w|--enable-push enable pushing to the new remote 24 | @EOF 25 | exit $1 26 | } 27 | 28 | # get default protocol from git config, or use "mixed" by default 29 | PROTOCOL=$(git config --get cms.protocol || echo mixed) 30 | if [ "$PROTOCOL" != "https" ] && [ "$PROTOCOL" != "ssh" ] && [ "$PROTOCOL" != "mixed" ]; then 31 | $ECHO "Unsupported value $PROTOCOL in cms.protocol (choose https, ssh, mixed)" 32 | exit 1 33 | fi 34 | 35 | READONLY=true 36 | FETCH=true 37 | COMMAND= 38 | TARGET= 39 | 40 | while [ "$#" != 0 ]; do 41 | case "$1" in 42 | -h | --help ) 43 | usage 0 44 | ;; 45 | --https ) 46 | INITOPTIONS="$INITOPTIONS $1" 47 | PROTOCOL=https 48 | shift 49 | ;; 50 | --ssh ) 51 | INITOPTIONS="$INITOPTIONS $1" 52 | PROTOCOL=ssh 53 | shift 54 | ;; 55 | --fetch ) 56 | FETCH=true 57 | shift 58 | ;; 59 | --no-fetch ) 60 | FETCH=false 61 | shift 62 | ;; 63 | -w | --enable-push ) 64 | READONLY=false 65 | shift 66 | ;; 67 | -*) 68 | echo Unknown option $1 69 | usage 1 70 | ;; 71 | *) 72 | if [ "$COMMAND" == "" ]; then 73 | COMMAND=$1 74 | elif [ "$TARGET" == "" ]; then 75 | TARGET=$1 76 | else 77 | echo Unexpected argument $1 78 | usage 1 79 | fi 80 | shift 81 | ;; 82 | esac 83 | done 84 | 85 | # initialize the local repository 86 | if [ -z "$CMSSW_BASE" ]; then 87 | echo "CMSSW environment not setup, please run 'cmsenv' before 'git cms-remote'." 88 | exit 1 89 | fi 90 | if ! [ -d $CMSSW_BASE/src/.git ]; then 91 | git cms-init --upstream-only $INITOPTIONS 92 | fi 93 | 94 | cd $CMSSW_BASE/src 95 | 96 | case "$COMMAND" in 97 | add ) 98 | if [ "$TARGET" == "" ]; then 99 | usage 1 100 | fi 101 | if [ "$PROTOCOL" == "ssh" ]; then 102 | git remote add $TARGET git@github.com:$TARGET/cmssw.git 103 | else 104 | git remote add $TARGET https://github.com/$TARGET/cmssw.git 105 | fi 106 | if [ "$READONLY" == "true" ]; then 107 | git remote set-url --push $TARGET disabled 108 | elif [ "$PROTOCOL" == "https" ]; then 109 | git remote set-url --push $TARGET https://github.com/$TARGET/cmssw.git 110 | else 111 | git remote set-url --push $TARGET git@github.com:$TARGET/cmssw.git 112 | fi 113 | if [ "$FETCH" == "true" ]; then 114 | git fetch $TARGET 115 | fi 116 | ;; 117 | * ) 118 | echo Unknown subcommand: $COMMAND 119 | usage 1 120 | ;; 121 | esac 122 | -------------------------------------------------------------------------------- /git-cms-rmpkg: -------------------------------------------------------------------------------- 1 | git-cms-addpkg -------------------------------------------------------------------------------- /git-cms-show-pr: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | function usage() { 4 | cat <<@EOF 5 | Usage: git cms-show-pr [] 6 | 7 | Description: 8 | Show the commits that are part of a pull request that has been opened or merged 9 | in the master branch, or in if it is specified. 10 | @EOF 11 | exit $1 12 | } 13 | 14 | # the number of the pull request 15 | PULL=$1 16 | [ "$PULL" ] || usage 1 17 | 18 | # for a backport, specify the target branch that was used 19 | BRANCH=$2 20 | [ "$BRANCH" ] || BRANCH=master 21 | 22 | # FIXME add an option to support alternate repositories ? 23 | REMOTE="official-cmssw" 24 | 25 | [ "$CMSSW_BASE" ] && cd $CMSSW_BASE/src 26 | 27 | # fetch the master branch from upstream 28 | git fetch -q $REMOTE $BRANCH 29 | 30 | # fetch the pull request 31 | git fetch -q $REMOTE pull/$PULL/head 32 | 33 | # find the branch point 34 | BRANCH_POINT=$(diff -u <(git rev-list --first-parent FETCH_HEAD) <(git rev-list --first-parent $REMOTE/$BRANCH) | sed -ne 's/^ //p' | head -n1 -) 35 | 36 | # show the commits in the pull request 37 | git log --no-decorate --oneline --reverse --topo-order FETCH_HEAD...$BRANCH_POINT 38 | -------------------------------------------------------------------------------- /git-cms-showtags: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | """:" 4 | python_cmd="python" 5 | python3 -V >/dev/null 2>&1 && python_cmd="python3" 6 | exec ${python_cmd} $0 ${1+"$@"} 7 | """ 8 | 9 | from optparse import OptionParser 10 | from commands import getstatusoutput 11 | from os import environ 12 | from os.path import join, exists 13 | from sys import exit 14 | 15 | def format(s, **kwds): 16 | return s % kwds 17 | 18 | if __name__ == "__main__": 19 | parser = OptionParser() 20 | opts, args = parser.parse_args() 21 | if not "CMSSW_VERSION" in environ: 22 | parser.error("You do not have CMSSW environment setup. Please do cmsenv.") 23 | if not "CMSSW_BASE" in environ: 24 | parser.error("You need to be in a CMSSW workarea for this. Create one with scram project CMSSW_X_Y_Z.") 25 | if 'CMSSW_GIT_HASH' in environ: 26 | cmssw_tag = environ['CMSSW_GIT_HASH'] 27 | else: 28 | cmssw_tag = environ['CMSSW_VERSION'] 29 | # If no git area is found. We are in a vanilla area. 30 | if not exists(join(environ["CMSSW_BASE"], "src/.git")): 31 | parser.error("You do not have any code checked out WRT the release") 32 | 33 | cmd = "cd $CMSSW_BASE/src ; git ls-tree --abbrev -d -r %(tag)s" 34 | error, out = getstatusoutput(format(cmd, tag="HEAD")) 35 | if error: 36 | parser.error("Error while getting tags for the current working area") 37 | lines = [x.replace("\t", " ") for x in out.split("\n") if x.count("/") == 1] 38 | table = [x.split(" ") for x in lines if x] 39 | baseTags = dict([(x[3], x[2]) for x in table]) 40 | 41 | error, out = getstatusoutput(format(cmd, tag = cmssw_tag)) 42 | if error: 43 | parser.error("Error while getting tags for this CMSSW release, %s" % cmssw_tag) 44 | lines = [x.replace("\t", " ") for x in out.split("\n") if x.count("/") == 1] 45 | table = [x.split(" ") for x in lines if x] 46 | newTags = dict([(x[3], x[2]) for x in table]) 47 | 48 | minPkg = max([len(x) for x in baseTags]) 49 | minTag = max([len(x) for x in baseTags.itervalues()]) 50 | 51 | for (k,v) in sorted(baseTags.iteritems()): 52 | if not k in newTags: 53 | print (format("%(package)s\t%(old)s\t%(new)s", 54 | package=k.ljust(minPkg, " "), 55 | old=v.ljust(minTag, " "), 56 | new="REMOVED")) 57 | continue 58 | if newTags[k] == v: 59 | continue 60 | print (format("%(package)s\t%(old)s\t%(new)s", 61 | package=k.ljust(minPkg, " "), 62 | old=v.ljust(minTag, " "), 63 | new=newTags[k])) 64 | -------------------------------------------------------------------------------- /git-cms-sparse-checkout: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # Includes in .git/info/sparse-checkout a list of the packages 3 | # which are modified between TAG1 and TAG2 4 | case `uname` in 5 | Darwin) ECHO=echo ;; 6 | *) ECHO="echo -e" ;; 7 | esac 8 | usage () { 9 | echo "git cms-sparse-checkout [options] TAG1 TAG2" 10 | echo 11 | echo "Options:" 12 | $ECHO "-h \tthis help message" 13 | $ECHO 14 | $ECHO "-d, --debug \tenable debug output" 15 | exit $1 16 | } 17 | 18 | DEBUG=0 19 | REF1= 20 | REF2= 21 | while [ "$#" != 0 ]; do 22 | case "$1" in 23 | -h | --help ) 24 | usage 0;; 25 | -d|--debug) 26 | DEBUG=1 27 | shift 28 | ;; 29 | --exclude-cvs-keywords) 30 | REGEX='^([^$]+$|[^$]*[$][^$]*$|([^$]*[$])($|[^RAIDLNSH]|(R[^eC]|A[^u]|I[^d]|D[^a]|L[^o]|N[^a]|S[^o]|H[^e])|(Re[^v]|RC[^S]|Au[^t]|Id[^:]|Da[^t]|Lo[^g]|Na[^m]|So[^u]|He[^a])|(Rev[^i]|RCS[^f]|Aut[^h]|Dat[^e]|Log[^:]|Nam[^e]|Sou[^r]|Hea[^d])|(Revi[^s]|RCSf[^i]|Auth[^o]|Date[^:]|Name[^:]|Sour[^c]|Head[^e])|(Revis[^i]|RCSfi[^l]|Autho[^r]|Sourc[^e]|Heade[^r])|(Revisi[^o]|RCSfil[^e]|Author[^:]|Source[^:]|Header[^:])|(Revisio[^n]|RCSfile[^:])|(Revision[^:])))' 31 | REGEX_OPT="-G" 32 | shift 33 | ;; 34 | -G) 35 | REGEX_OPT="-G" 36 | REGEX="$2"; shift ; shift 37 | ;; 38 | -*) 39 | echo Unknown option $1 ; usage 1 ;; 40 | *) 41 | if [ "$REF1" == "" ]; then 42 | REF1="$1" 43 | elif [ "$REF2" = "" ]; then 44 | REF2="$1" 45 | else 46 | echo "Too many tags / branches specified." ; exit 1 47 | fi 48 | shift 1 49 | ;; 50 | esac 51 | done 52 | 53 | BASH_FULL_VERSION=$((${BASH_VERSINFO[0]} * 10000 + ${BASH_VERSINFO[1]} * 100 + ${BASH_VERSINFO[2]})) 54 | if (( BASH_FULL_VERSION >= 40100 )); then 55 | # bash 4.1 or newer 56 | if [ $DEBUG == 0 ]; then 57 | # send debug messages to /dev/null 58 | exec {debug}> /dev/null 59 | else 60 | # send debug messages to stderr 61 | exec {debug}>&2 62 | # pass the debug option to subcommands 63 | DEBUG_OPT=-d 64 | # enable shell tracing 65 | set -x 66 | fi 67 | else 68 | # bash 4.0 or older 69 | debug=12 70 | if [ $DEBUG == 0 ]; then 71 | # send debug messages to /dev/null 72 | exec 12> /dev/null 73 | else 74 | # send debug messages to stderr 75 | exec 12>&2 76 | # pass the debug option to subcommands 77 | DEBUG_OPT=-d 78 | # enable shell tracing 79 | set -x 80 | fi 81 | fi 82 | 83 | case `git --version` in 84 | git\ version\ 1.7*) 85 | # git 1.7.x does not support a leading slash in .gitignore and .git/info/sparse-checkout 86 | LEADING_SLASH= 87 | ;; 88 | *) 89 | LEADING_SLASH=/ 90 | ;; 91 | esac 92 | 93 | git config core.sparsecheckout true 94 | INFO_DIR=`git rev-parse --show-toplevel`/.git/info/ 95 | touch $INFO_DIR/sparse-checkout 96 | cp -f $INFO_DIR/sparse-checkout $INFO_DIR/sparse-checkout-new 97 | for x in `git diff $REGEX_OPT $REGEX $REF1..$REF2 --name-only --no-renames | grep -v ".gitconfig" | cut -f1,2 -d/ | sort -u`; do 98 | echo "$x" | sed -e "s|[/]*$|/|;s|^/*|${LEADING_SLASH}|" >> $INFO_DIR/sparse-checkout-new 99 | done 100 | for x in `git diff $REF1..$REF2 | grep '^old mode' -C 1 | grep '^diff --git' | sed -e 's|.* ||;s|b/||' | grep -v ".gitconfig" | cut -f1,2 -d/ | sort -u`; do 101 | echo "$x" | sed -e "s|[/][/]*$|/|;s|^/*|${LEADING_SLASH}|" >> $INFO_DIR/sparse-checkout-new 102 | done 103 | 104 | cat $INFO_DIR/sparse-checkout-new | sort -u > $INFO_DIR/sparse-checkout 105 | rm -f $INFO_DIR/sparse-checkout-new 106 | -------------------------------------------------------------------------------- /git-cms-squash-topic: -------------------------------------------------------------------------------- 1 | git-cms-merge-topic -------------------------------------------------------------------------------- /git-proxy: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # connect to the Git repository through a SOCKS proxy 4 | 5 | 6 | # default setting is to use port 1080 on the local host 7 | proxy="localhost:1080" 8 | from="default" 9 | 10 | # check if there is a value in the git configuration 11 | if git config --get socks.proxy >& /dev/null; then 12 | proxy=`git config --get socks.proxy` 13 | from="git's socks.proxy" 14 | fi 15 | 16 | # check if a generic proxy has been defined in the environment 17 | if [ -n "$ALL_PROXY" ]; then 18 | proxy="$ALL_PROXY" 19 | from="\$ALL_PROXY" 20 | fi 21 | if [ -n "$all_proxy" ]; then 22 | proxy="$all_proxy" 23 | from="\$all_proxy" 24 | fi 25 | 26 | # check if a SOCKS proxy has been defined in the environment 27 | if [ -n "$SOCKS_PROXY" ]; then 28 | proxy="$SOCKS_PROXY" 29 | from="\$SOCKS_PROXY" 30 | fi 31 | if [ -n "$socks_proxy" ]; then 32 | proxy="$socks_proxy" 33 | from="\$socks_proxy" 34 | fi 35 | if [ -n "$SOCKS5_PROXY" ]; then 36 | proxy="$SOCKS5_PROXY" 37 | from="\$SOCKS5_PROXY" 38 | fi 39 | if [ -n "$socks5_proxy" ]; then 40 | proxy="$socks5_proxy" 41 | from="\$socks5_proxy" 42 | fi 43 | 44 | # check if a git specific SOCKS proxy has been defined in the environment 45 | if [ -n "$GIT_SOCKS_PROXY" ]; then 46 | proxy="$GIT_SOCKS_PROXY" 47 | from="\$GIT_SOCKS_PROXY" 48 | fi 49 | 50 | function usage() { 51 | cat << @EOF 52 | Usage: 53 | `basename $0` HOST PORT 54 | 55 | Helper script to connect to a Git repository over the git:// protocol at host HOST and port PORT through a SOCKS proxy at $proxy ($from). 56 | 57 | To use the proxy for all git:// traffic, set the core.gitproxy option to "git-proxy": 58 | 59 | git config core.gitproxy "git-proxy" 60 | 61 | 62 | To use the proxy only for some reporitories, use the syntax explained in git-config(1). 63 | 64 | To configure which proxy to use, set an appropriate environment variable (see below) or socks.proxy option to the proxy address, for example "localhost:1080": 65 | 66 | git config socks.proxy "localhost:1080" 67 | 68 | 69 | The address of the proxy is read from (in order of priority): 70 | - the GIT_SOCKS_PROXY environment variable; 71 | - the SOCKS_PROXY or SOCKS5_PROXY environment variable; 72 | - the ALL_PROXY environment variable (see curl(1)); 73 | - the socks.proxy git option; 74 | - the default value: localhost:1080 . 75 | @EOF 76 | } 77 | 78 | if [ -z "$1" ] || [ -z "$2" ] || [ -n "$3" ]; then 79 | usage 80 | exit 1 81 | fi 82 | 83 | # connect through the specifid proxy 84 | nc -x "$proxy" "$1" "$2" 85 | -------------------------------------------------------------------------------- /init.sh: -------------------------------------------------------------------------------- 1 | CURRENT_PATH=$PWD/`dirname $0` 2 | export PATH=$CURRENT_PATH:$PATH 3 | export MANPATH=$CURRENT_PATH/docs/man:$MANPATH 4 | -------------------------------------------------------------------------------- /share/etc/profile.d/S99cms-git-tools-completion.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # completion function used 4 | # - for `git-cms-addpkg`, called by `complete` 5 | # - for `git cms-addpkg`, called by `__git_complete_command` during the 6 | # completion for the `git` command 7 | 8 | # Note: _git_cms_addpkg() exits with a non-zero status to indicate the failure 9 | # to return any completions. 10 | # __git_complete_command ignores the return status of the helper function, and 11 | # will fall back to the default completion showing files and directories. 12 | # This is consistent with the behaviour of the other git subcommands. 13 | 14 | function _git_cms_addpkg() { 15 | # if CMSSW_BASE is not defined, do not return any completions 16 | if [ -z "${CMSSW_BASE}" ]; then 17 | COMPREPLY=() 18 | return 1 19 | fi 20 | 21 | if [ -d "${CMSSW_BASE}/src/.git" ]; then 22 | # if the git repository in the local area has already been initialised, 23 | # list all packages (Dir/SubDir) in the git repository 24 | local PACKAGES="$(git -C ${CMSSW_BASE}/src ls-files --full-name 2> /dev/null | cut -d/ -s -f1-2 | sort -u)" 25 | elif [ "${CMSSW_RELEASE_BASE}" ] && [ -d "${CMSSW_RELEASE_BASE}/src" ]; then 26 | # otherwise, if a release area is defined, list all packages from it 27 | local PACKAGES="$(cd ${CMSSW_RELEASE_BASE}/src 2> /dev/null; ls -d -1 */*/ | cut -d/ -s -f1-2 | sort -u)" 28 | fi 29 | 30 | # if listing the packages failed or returned an empty list, do not return any completion 31 | if [ -z "${PACKAGES}" ]; then 32 | COMPREPLY=() 33 | return 1 34 | fi 35 | 36 | local PREV="${COMP_WORDS[$((COMP_CWORD - 1))]}" 37 | if [ "$PREV" == "-f" ] || [ "$PREV" == "--file" ]; then 38 | # -f/--file takes a file as argument, fall back to the default completion 39 | compopt -o default 40 | COMPREPLY=() 41 | else 42 | # complete the word under the cursor using the list of packages 43 | COMPREPLY=($(compgen -W "${PACKAGES}" "${COMP_WORDS[$COMP_CWORD]}")) 44 | fi 45 | } 46 | 47 | complete -F _git_cms_addpkg git-cms-addpkg 48 | -------------------------------------------------------------------------------- /tests/test_wrappers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ "X$WORKSPACE" = X ]; then 3 | SHUNIT_TMPDIR="$WORKSPACE" 4 | fi 5 | export CUR_PATH=$PWD 6 | export PATH=$PWD:$PATH 7 | 8 | testPaths () { 9 | gitCmsAddpkg="`which git-cms-addpkg`" 10 | gitCmsMergeTopic="`which git-cms-merge-topic`" 11 | gitCmsCheckdeps="`which git-cms-checkdeps`" 12 | assertEquals "Not testing the correct git-cms-addpkg" `dirname "$gitCmsAddpkg"` "$CUR_PATH" 13 | assertEquals "Not testing the correct git-cms-merge-topic" `dirname "$gitCmsMergeTopic"` "$CUR_PATH" 14 | assertEquals "Not testing the correct git-cms-checkdeps" `dirname "$gitCmsCheckdeps"` "$CUR_PATH" 15 | assertTrue "Git should be present and working" "git --version" 16 | } 17 | 18 | testCheckdeps(){ 19 | which git-cms-checkdeps 20 | cd $SHUNIT_TMPDIR 21 | assertTrue "Release should not be there" "[ ! -d CMSSW_7_0_0_pre0 ]" 22 | assertTrue "SCRAM is missing" "scram project CMSSW_7_0_0_pre0" || return 1 23 | assertTrue "Should be able to create release" "[ -d CMSSW_7_0_0_pre0 ]" 24 | assertFalse "Should require CMSSW environment" "git-cms-checkdeps" 25 | cd CMSSW_7_0_0_pre0 26 | eval `scram run -sh` 27 | assertTrue "Should checkout FWCore/Framework" "git-cms-addpkg FWCore/Framework" 28 | # Test $Id:$ 29 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo 'nbcdjksnckjsa\$Id: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 30 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 31 | assertEquals "Should CVS Ids should be ignored" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 32 | # Test $Author:$ 33 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '\$Author: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 34 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 35 | assertEquals "Should CVS Ids should be ignored" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 36 | # Test $Log:$ 37 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '\$Log: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 38 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 39 | assertEquals "Should CVS Ids should be ignored" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 40 | # Test $Revision:$ 41 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '\$Revision: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 42 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 43 | assertEquals "Should ignore CVS \$Revision\$" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 44 | # Test $Revision:$ 45 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo 'cdjknsncjksanadjks\$Revision: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 46 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 47 | assertEquals "Should ignore CVS \$Revision\$ (with extra stuff)" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 48 | # Test $Source:$ 49 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo ' \$Source: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 50 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 51 | assertEquals "CVS Source should have been ignored" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 52 | # Test $Source:$ 53 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '\$Source: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 54 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 55 | assertEquals "CVS Source (with space) should have be ignored" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 56 | # Test $Header:$ 57 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '\$Header: Foo$' >> src/FWCore/Framework/interface/EDLooper.h" 58 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 59 | assertEquals "CVS Header should have be ignored" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 60 | # Test Two keywords 61 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '\$Revision: Foo$ $Id:bar $' >> src/FWCore/Framework/interface/EDLooper.h" 62 | assertTrue "Should run checkdeps 1" "git-cms-checkdeps -a" 63 | assertEquals "Two CVS keywords should have been ignored" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 64 | 65 | # Check for a real change. 66 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '\n//foo' >> src/FWCore/Framework/interface/EDLooper.h" 67 | assertTrue "Should run checkdeps" "git-cms-checkdeps" 68 | git cms-checkdeps 69 | assertEquals "Should have created FWCore/Framework only" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 70 | assertTrue "Should run checkdeps" "git-cms-checkdeps -a" 71 | assertEquals "Should have created a bunch of stuff" "10" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 72 | rm -rf src 73 | # Check for half backed keyword. 74 | assertTrue "Should checkout FWCore/Framework" "git-cms-addpkg FWCore/Framework" 75 | assertTrue "File src/FWCore/Framework/interface/EDLooper.h should be there" "echo '// $Id:' >> src/FWCore/Framework/interface/EDLooper.h" 76 | assertTrue "Should run checkdeps" "git-cms-checkdeps" 77 | assertEquals "Should have created FWCore/Framework only" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 78 | assertTrue "Should run checkdeps" "git-cms-checkdeps -a" 79 | assertEquals "Should have created a bunch of stuff" "10" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 80 | eval `scram unsetenv -sh` 81 | } 82 | 83 | testAddpkg(){ 84 | cd $SHUNIT_TMPDIR 85 | # Without CMSSW environment. 86 | assertEquals "\$CMSSW_VERSION should not be set." "" "$CMSSW_VERSION" 87 | assertFalse "Needs a tag if \$CMSSW_VERSION not there" "git-cms-addpkg FWCore/Version" 88 | assertFalse "Should not create a directory" "[ -d src/FWCore/Version ]" 89 | # With CMSSW environment. 90 | rm -rf CMSSW_7_0_0_pre0 91 | assertTrue "SCRAM is missing" "scram project CMSSW_7_0_0_pre0" || return 1 92 | assertTrue "Should be able to create release" "[ -d CMSSW_7_0_0_pre0 ]" 93 | assertFalse "Should require CMSSW environment" "git-cms-checkdeps" 94 | cd CMSSW_7_0_0_pre0 95 | eval `scram run -sh` 96 | assertTrue "Should complete successfully" "git-cms-addpkg FWCore/Version CMSSW_7_0_0_pre0" 97 | assertTrue "Should have created FWCore/Version" "[ -d src/FWCore/Version ]" 98 | assertEquals "Should have created FWCore/Version only" "1" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 99 | assertFalse "Should not run with a different tag than then initial one" "git-cms-addpkg FWCore/Version CMSSW_6_2_0_pre8" 100 | assertTrue "Should checkout a different package" "git-cms-addpkg DataFormats/TestObjects CMSSW_7_0_0_pre0" 101 | assertEquals "Should have created 2 packages" "2" `find src -maxdepth 2 -mindepth 2 ! -path "**/.git/*" -type d | wc -l` 102 | assertTrue "Should have created DataFormats/TestObjects" "[ -d src/DataFormats/TestObjects ]" 103 | eval `scram unsetenv -sh` 104 | } 105 | 106 | oneTimeSetup() { 107 | mkdir "${outputDir}" 108 | stdoutF="${outputDir}/stdout" 109 | stderrF="${outputDir}/stderr" 110 | } 111 | 112 | #Download shunit2 suite if needed. 113 | if [ ! -f tests/shunit2-2.1.6/src/shunit2 ]; then 114 | pushd tests 115 | curl -O http://shunit2.googlecode.com/files/shunit2-2.1.6.tgz 116 | tar xzf shunit2-2.1.6.tgz 117 | popd 118 | fi 119 | 120 | source tests/shunit2-2.1.6/src/shunit2 121 | --------------------------------------------------------------------------------