I have been slowly evolving some code for Git and VSS interop based on a quest I started a while ago
And the code is now working, some parts have been updated without test (such as the init) and I am not 100% sure everything is doing what it should/is the best way and some parts seem really round the houses!
Its certainly past the point where it needs some input.
The basic concept is
- "Pulling" from source safe is achieved by keeping a separate "vss_branch"
- vss_branch is kept up to kept up to date with source safe via a full source safe get
- master treats vss_branch as its "upstream/origin" so master pulls from vss_branch
- "Pushing" to source safe
- is achieved by figuring out what is different between master and vss_branch
- saving and then pushing to vss_branch
- then I go through all the modified/deleted/added files, and applying the appropriate operation e.g. checking them out and checking them in
The code is currently used in the context of git, vss, beyondcompare and trackgear
I am keeping an up to date version here:
Code at time of question:
#--useful aliases
alias gitremove="git ls-files --deleted -z | xargs -0 git rm"
alias bcompare="START / \"C:\Program Files (x86)\Beyond Compare 3\BCompare.exe\""
alias initgitss=InitGitAndSourceSafeProject
alias ssclone="ss get "$CURRENT_SOURCE_SAFE_PROJECT" -W -R -Q -Y$SSNAME -I-N"
alias ssdiff="ss Diff -Y$SSNAME"
#----These Need Setting:
##Your source safe project
CURRENT_SOURCE_SAFE_PROJECT=
##You Working directory
CURRENT_PROJ_DIR=
#--For Source Safe Comments
ACTIVE_TRACK_REF=
PROJECT_NAME=
##Your BeyondCompare Session
#its better to create a beyond compare session so you can set it up how you like
BEYOND_COMPARE_SESSION=
#----SysVars
REF_APPEND="_REF"
#--variable set up helper
sset()
{
if [ $# -eq 0 ]
then
echo "No arguments supplied, please supply the SS project name"
fi
CURRENT_SOURCE_SAFE_PROJECT=1ドル
CURRENT_PROJ_DIR=$(pwd)
}
#--create a git project from a VSS project and set everything up ---#
InitGitAndSourceSafeProject()
{
if [ -z ${CURRENT_SOURCE_SAFE_PROJECT+x} ];
then echo "CURRENT_SOURCE_SAFE_PROJECT is unset";
exit;
fi
git init
#get all the SS sourcecode
echo "Switching to $CURRENT_SOURCE_SAFE_PROJECT"
ss cp $CURRENT_SOURCE_SAFE_PROJECT
ssclone
git add --all
git commit -m "Initial Source Safe Clone"
#create fake upstream
git checkout -b vss_branch
#create a dev branch
git checkout -b dev
git checkout master
#set master to treat "vss_branch" as upstream
git branch --set-upstream-to vss_branch
SynchMasterToSS
}
#---reset to current project---#
sreset()
{
echo "Make sure we are in the correct source safe project"
ss CP $CURRENT_SOURCE_SAFE_PROJECT
ss project
}
quietsreset()
{
ss CP $CURRENT_SOURCE_SAFE_PROJECT -O-
}
#----Commit *one file* -that is already added- to SS----#
sscommitone()
{
FULLPATH=1ドル
DIR=$(echo ${FULLPATH%/*})
SS_COMMENT="$PROJECT - TGR: $TGR\n\n"
#go to correct place in working directory
pushd $DIR
#checkout file without overwriting local copy
#echo Y | ss checkout "$FULLPATH" -G-WR -Y$SSNAME
ss checkout "$FULLPATH" -G-WR -Y$SSNAME -I-Y
#check in the file with comment
#echo Y | ss checkin "1ドル" -C"$SS_COMMENT" -W -Y$SSNAME
ss checkin "1ドル" -C"$SS_COMMENT" -W -Y$SSNAME -I-Y
#go back to the directoy we were in -root-
popd
}
#----bulk commit---#
sscommit()
{
for file in 1ドル; do
sscommitone $file
done
}
#----bulk add-----#
AddEachNewFile()
{
printf "\n\nAdding files requires us to loop, so we can add to the correct directory"
for file in 1ドル; do
printf "\n--Resetting Dir---\n"
quietsreset
new_file=$(echo ${file##*/})
directory=$(echo ${file%/*})
#cp to folder
echo "Directory is: $directory"
quietsreset
test=$(ss CP $directory 2>&1 | grep -c 'exist' 2>&1)
if (( "1"== $test ));
then
echo "Did not to find directory! It does not exist!....yet :)";
new_directory=$directory;
last_directory=$directory;
while (( "1"== $test ));
do
echo "->This parent directory does not exist, try going up";
echo "---trying to cp to $new_directory"
last_directory=$(echo ${new_directory})
new_directory=$(echo ${new_directory%/*})
quietsreset
test=$(ss CP $new_directory 2>&1 | grep -c 'exist' 2>&1)
echo "[+]"
done
echo "Directory does not exit, need to add $last_directory";
ss Add $last_directory -R -C"$SS_COMMENT" -Y$SSNAME
else
echo "Directory already exist, need to add file: ${file}";
ss Add $file -C"$SS_COMMENT" -Y$SSNAME
fi
done
}
#use this function for when you forgot to fill in TGR info
ptgr()
{
updateModDelAddVars 1ドル
printTGRInfo
}
#--- vars needed for to perform ss operations ----
updateModDelAddVars()
{
#files to check out and in again from SS
MODIFIED_FILES=$( git diff --name-only 1ドル --diff-filter=M)
#files to add to SS
ADDED_FILES=$( git diff --name-only 1ドル --diff-filter=A)
#file to delete from SS
DELETED_FILES=$( git diff --name-only 1ドル --diff-filter=D)
}
printTGRInfo()
{
printf "Please update the TGR with the following changed files:"
printf " \n***********************\n"
printf "|--Modified Files --\n\n"
printf "$MODIFIED_FILES"
printf " \n--\n"
printf "|--New Files --\n\n"
printf "$ADDED_FILES"
printf " \n--\n"
printf "|--Deleted Files --\n\n"
printf "$DELETED_FILES"
printf " \n\n ********************* \n"
}
##------Pull -todo- find out what other command is assigned to sspull!
sspullb()
{
if [ ! -d ".git" ]; then
echo "Must be ran from root git/ss rep"
exit;
fi
#save branch we are on
BRANCH=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),1,円')
#jump to "fake upstream"
git checkout vss_branch
#update vss branch to match vss..
echo "grabbing all files from sourcesafe"
ssclone
##figure out files I have changed
FILES=$( git diff --name-only master vss_branch)
##grab the recent history for those files & everything else seperately
NOW=$(date)
SSFILEHISTORY=$(ss History . $FILES -#3)
SSHISTORY=$(ss History . -#3)
##now add & commit those files with a comment
git add --all
MESSAGE=$(echo -e "Source safe sync: $NOW \n Changes to my files: \n $SSFILEHISTORY \nChanges To Other Files:\n $SSHISTORY")
git commit -a -m"$MESSAGE"
#jump back to branch that wants to pull
git checkout $BRANCH
git pull
}
##------ 'Push'
sspush()
{
if [ ! -d ".git" ]; then
echo "Must be ran from root git/ss rep"
exit;
fi
BRANCH=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),1,円')
##-TODO- check for git error at checkout attempt instead!
##we might have some work uncommitted (naughty)
##git stash
#get a suitable amount of git master comments for SS comment SS comment IS limted to 500chars though...
GIT_COMMENT=$(git log --pretty=format:"%h %s" --no-merges -n 3)
git log --no-merges > fullGitHistory.githistory
#figure out files that need to go into source safe
updateModDelAddVars vss_branch
#ok now make vss_branch up to date -this keeps git happy :)-
#the odd syntax is due to the fact we are treating vss_branch as our upstream
git push . HEAD:vss_branch
#check the file in with latest git comments but keep files as writeable
#--TODO-- read -p "Please enter the TGR this commit relates to: " TGR
TGR=$ACTIVE_TRACK_REF
#Add each file (and possible directory)
printf "\n---------------------------------------------------\n"
printf "Adding new files \n->\n $ADDED_FILES"
printf "\n---------------------------------------------------\n"
SS_COMMENT="$PROJECT - TGR: $TGR \n\n$GIT_COMMENT"
AddEachNewFile $ADDED_FILES
printf "\n---------------------------------------------------\n"
printf "Deleting old files \n->\n $DELETED_FILES"
printf "\n---------------------------------------------------\n"
ss Delete $DELETED_FILES -Y$SSNAME -I-N
#Loop through the files, checking in and out from correct directory
printf "\n---------------------------------------------------\n"
printf "Overwriting modified files \n->\n $MODIFIED_FILES"
printf "\n---------------------------------------------------\n"
sscommit $MODIFIED_FILES
#update git history file -this way SS has all the rich comment history I store with git despite SS's 500 comment character limit-
ss Add fullGitHistory.githistory -C"Log of all git history"
sscommitone fullGitHistory.githistory
#now print the message needed for the TGR comment
printTGRInfo
#"unpop" all the things we just did to restore working tree
git checkout $BRANCH
##--TODO-- check for git error at checkout attempt instead!
##git stash apply
}
#replace Source-safe code with my master branch code
masterpushss()
{
echo "to master branch"
git checkout master
sspush
}
#merge master with source safe code
masterpullss()
{
git checkout master
sspullb
}
#get master to perform pull and push
synch()
{
masterpullss
masterpushss
}
##----True Diff---
hardrefupdate()
{
REF_FOLDER="$CURRENT_PROJ_DIR$REF_APPEND"
rm -rf $REF_FOLDER
updateref
}
updateref()
{
REF_FOLDER="$CURRENT_PROJ_DIR$REF_APPEND"
if [ ! -d $REF_FOLDER ]; then
mkdir $REF_FOLDER
fi
pushd $REF_FOLDER
ssclone
popd
}
compare_toREF()
{
if [ -z "$BEYOND_COMPARE_SESSION" ]; then
bcompare $CURRENT_PROJ_DIR $REF_FOLDER /iu /filters="-*.scc;-*.opensdf;-*.sdf;-*.orig" /qc=size
else
bcompare $BEYOND_COMPARE_SESSION
fi
}
#should only be needed for sanity checks -diff with vss_branch *should* achieve the same-
diffallss()
{
if [ -z ${CURRENT_PROJ_DIR+x} ];
then echo "CURRENT_PROJ_DIR is unset";
exit;
fi
UpdateRef
compare_toREF
}
harddiffallss()
{
if [ -z ${CURRENT_PROJ_DIR+x} ];
then echo "CURRENT_PROJ_DIR is unset";
exit;
fi
hardrefupdate
compare_toREF
}
#PS1='[\u@\h`__git_ps1` \W]\$
-
\$\begingroup\$ I will admit this has become more of a "is it possible" then a proper solution :p \$\endgroup\$chrispepper1989– chrispepper19892014年11月25日 09:11:05 +00:00Commented Nov 25, 2014 at 9:11
1 Answer 1
A couple of minor issues, from top to bottom.
When you need to embed double-quotes in a string, and you don't need to embed variables inside, then it's easier to use single-quotes. So instead of this:
alias bcompare="START / \"C:\Program Files (x86)\Beyond Compare 3\BCompare.exe\""
This is easier:
alias bcompare='START / "C:\Program Files (x86)\Beyond Compare 3\BCompare.exe"'
No need to break out of the double-quotes here:
alias ssclone="ss get "$CURRENT_SOURCE_SAFE_PROJECT" -W -R -Q -Y$SSNAME -I-N"
You could embed the variable simply:
alias ssclone="ss get $CURRENT_SOURCE_SAFE_PROJECT -W -R -Q -Y$SSNAME -I-N"
Regarding this piece:
if [ -z ${CURRENT_SOURCE_SAFE_PROJECT+x} ];
...What the heck is ${CURRENT_SOURCE_SAFE_PROJECT+x}
???
I'd appreciate if you could explain in comments :-)
Especially a keyword would be nice that I can search for in man bash
.
I'd be really interested to know.
As it stands, it seem to me the expression will always evaluate to the letter "x",
which is not empty, so the if
will always be false.
Unnecessary ;
at the end of some lines:
then echo "CURRENT_SOURCE_SAFE_PROJECT is unset"; exit;
Remove those.
In some ss
commands you use cp
, in others you use CP
.
I suggest to be consistent and stick with the same style everywhere.
The echo
in a subshell here is unnecessary:
DIR=$(echo ${FULLPATH%/*})
This is better:
DIR=${FULLPATH%/*}
The same goes for these:
new_file=$(echo ${file##*/}) directory=$(echo ${file%/*})
In AddEachNewFile
you have a for-loop with the body not well-indented:
for file in 1ドル; do printf "\n--Resetting Dir---\n" quietsreset
In the same method you also have an if
block not well-indented.
I suggest to fix these, as they hurt readability and can easily lead to bugs.
No need to quote exist
here:
test=$(ss CP $directory 2>&1 | grep -c 'exist' 2>&1)
This is the same and simpler:
test=$(ss CP $directory 2>&1 | grep -c exist 2>&1)
The rest of the code has similar issues to the ones I already pointed out:
- bad indents
- unnecessary trailing
;
- unnecessary quotes
- unnecessary
echo
subshells
Review the entire code, and follow the suggestions above.
When done, copy-paste your code on http://www.shellcheck.net/#, and correct the remaining warnings it tells you.
-
1\$\begingroup\$ Some great suggestions, thank you janos. I will read through and update accordingly. Regarding the updated code, should I just put it in an edit? As for the +x. I honestly for the life of me can't remember (comments ftw) so its either a typo or a bad attempt to check that the folder exists. \$\endgroup\$chrispepper1989– chrispepper19892014年12月09日 15:18:37 +00:00Commented Dec 9, 2014 at 15:18
-
1\$\begingroup\$ Hi @chrispepper1989, no, you shouldn't edit the code in your question, as that would invalidate my review. You can post a new question with the revised version for another round of reviews if you still need. \$\endgroup\$janos– janos2014年12月09日 15:26:38 +00:00Commented Dec 9, 2014 at 15:26
-
\$\begingroup\$ I was wondering new question or an ---Update--- to the question? \$\endgroup\$chrispepper1989– chrispepper19892014年12月09日 16:43:48 +00:00Commented Dec 9, 2014 at 16:43
-
\$\begingroup\$ Don't wonder: new question is the way we do here. It's also better for you, more questions usually lead to more rep ;-) \$\endgroup\$janos– janos2014年12月09日 17:10:27 +00:00Commented Dec 9, 2014 at 17:10