Pre-commit hook (on a local cloned SubGit repo) to automatically lock .uasset files if non locked by anyone, or fail if any file is locked by another user

I want to improve this script to be more generic and also achieve faster performance. Also, I’m sharing it just in case anyone else might find it useful. Any suggestions?

Here’s a link to the github gist that contains this: https://gist.github.com/nahuelarjonadev/dea44597af6feb1378c4a76292972520

### Parameters

# Change SVN_USER to the SVN username you configured in subgit
SVN_USER="firstname.lastname"
# Remote url. Should end with trunk/ or branches/ . Assumes same folder name on svn and git
SVN_REPO="https://url/path/to/remote/svn/repo/trunk/"
# Currently only checks locks for files with .uasset extension
GREP_FILE_PATTERN_TO_INSPECT="\.uasset$"
# Pattern to match usernames other than your own on the lock error msg
GREP_USERNAME_PATTERN="[[:alpha:]]\+\.[[:alpha:]]\+"

### Start of the hook

# Only to be used for the lock msg. Not necessary...
CURRENT_BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
# leave as 0, used for aborting the commit if a non-owned lock is found
COMMIT_SHOULD_FAIL=0
# Array of relative file paths (to git project) from staged files that should be locked
FILES_TO_LOCK=$(git diff --cached --name-only | grep $GREP_FILE_PATTERN_TO_INSPECT)

for FILE in $FILES_TO_LOCK
do
	PATH_TO_FILE_IN_SVN=$SVN_REPO$FILE
	# Try to apply a lock. If the file is already locked, grab the lock owner's username
	# 2>&1 redirects stderr to stdout, to pipe the error msg into grep for parsing it
	# 1st grep would grab part of the error msg printed if the file is already locked
	# 2nd grep would grab the lock owner's username with format GREP_USERNAME_PATTERN
	LOCK_OWNER=$(svn lock $PATH_TO_FILE_IN_SVN -m "working on ${CURRENT_BRANCH_NAME}" 2>&1 \
		| grep -o "already locked by user .\+'" \
		| grep -o $GREP_USERNAME_PATTERN)
	if [ $LOCK_OWNER ] && [ $LOCK_OWNER != $SVN_USER ] # If someone else locked it
	then
	  echo "Error: File ${FILE} locked by ${LOCK_OWNER}"
		COMMIT_SHOULD_FAIL=1
	fi
done

if [ $COMMIT_SHOULD_FAIL -eq 1 ] # If at least 1 file was locked by another user
then
  echo '--Commit ABORTED--'
  exit 1 # Exiting with exit-code 1 makes the entire commit process abort
fi

For instance, I’m accessing the remote repo once per file. When the round-trip is long that’s quite inefficient if the commit contains several .uasset files. Instead, it would be cool to batch all files info request on a single svn info request. I don’t know if that’s possible.

Also, the way I’m grabbing the Lock owner username is too hacky, but at least it does the trick for my case. Couldn’t succeed to grab a string from between two single quotes on the second grep. Instead, I’m matching the username pattern which of course only works in my scenario where all svn usernames used in my company are of the form name.lastname

Ok. So now I have a real issue. I’m getting the following error

remote: Fetching revisions from SVN repository: remote: up to date remote: Sending commits to SVN repository: remote: remote: SubGit ERROR REPORT (SubGit version 3.3.9 ('Bobique') build #4351): remote: remote: You've received this message because SubGit (http://subgit.com/) is installed in your repository remote: and an error that needs to be dealt with has occurred in SubGit translation engine. remote: remote: TEMPORARY ERROR: remote: Failed to push some refs to Subversion repository. remote: svn: E170007: No lock on path '/svn/[file path].uasset' (Status /svn/[file path].uasset on PUT Request) remote: svn: E175002: PUT of '/svn//svn/[file path].uasset': 423 Locked (https://[svn server ip]) remote: svn: E175002: PUT request failed on '/svn/[file path].uasset' remote: svn: E175002: PUT of '/svn/[file path].uasset': 423 Locked (https://[ svn server ip]) remote: svn: E175002: PUT request failed on '/svn/[file path].uasset' remote: remote: remote: CURRENT STATE: remote: Both Git and Subversion repository are open for pushes or commits. remote: Your commit was not committed, but you may retry it. remote: remote: TO RECOVER: remote: A) Address the problem if possible and then retry commit remote: OR remote: B) Run on the server remote: $ subgit uninstall /[bare repo path]/. remote: remote: IMPORTANT: As soon as SubGit is uninstalled, both Git and Subversion repositories remote: will become open, but no synchronization will take place. remote: remote: TO REPORT: remote: Report an issue at http://issues.tmatesoft.com/ remote: You may find logs on the server at '/[path to logs]' remote: remote: THANK YOU! To [bare repo path] ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to '[bare repo path]'

Basically, SubGit is unable to detect that I locked a file. I thought that by virtue of having the svn credentials (username and password) setup on SubGit as the ones I use with svn lock [url to file] the thing would’ve worked. But apparently not. How can I solve this?

Hello!

It’s not clear enough from the error message why it occurs, it requires a deeper investigation. Could you please advise if the SVN user account you are using in the pre-commit hook is the same that SubGit uses to access the SVN repository? If yes, could you please provide us with SubGit logs from the affected repository for analysis? Also, the regular logs are not the most detailed, could it be possible to set logLevel setting in SubGit configuration file in that repository to finest? This would allow to collect the most detailed log that would be very helpful for analysis. But note, that this log level will collect everything, including information that may be sensitive.