5
\$\begingroup\$

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]\$ 
asked Nov 24, 2014 at 16:24
\$\endgroup\$
1
  • \$\begingroup\$ I will admit this has become more of a "is it possible" then a proper solution :p \$\endgroup\$ Commented Nov 25, 2014 at 9:11

1 Answer 1

3
\$\begingroup\$

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.

answered Dec 6, 2014 at 16:46
\$\endgroup\$
4
  • 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\$ Commented 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\$ Commented Dec 9, 2014 at 15:26
  • \$\begingroup\$ I was wondering new question or an ---Update--- to the question? \$\endgroup\$ Commented 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\$ Commented Dec 9, 2014 at 17:10

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.