Getting project name in post-commit subversion hook - bash

I have a subversion repository laid out like this:
Repo
ProjectA
trunk
branches
tags
ProjectB
trunk
branches
tags
I'm trying to write a post-commit hook script that just applies to one project, but I just learned that they are housed at the root of the repository.
The only two parameters I get are the Repository path and Revision number. Is there any way for me to execute this script for just a particular project?
Thanks,
Solution:
Ultimate solution went something like this:
#!/bin/bash
REPOS="$1"
REV="$2"
if svnlook changed -r $REV $REPOS | grep ProjectA; then
echo "do stuff"
fi

yes, use svnlook to get the list of files modified in the committed revision, then grep on the names with a suitable regex to determine whether the path the post-commit contains your project name in the correct place, if it does execute the code, otherwise, jump to the end of the script and return 0.

I came here looking for the answer to this question for VisualSVN on a Windows 2012 Server. After gathering some more information, here is the solution I came up with for a Windows batch file post-commit hook on VisualSVN that loads a PHP script on a development server to cause the specific project to be deployed to that server. The hook command is one line:
svnlook changed "%1" | findstr /L "ProjectA/trunk/" && powershell -Command "Invoke-WebRequest http://192.168.0.177/checkout_on_commit/checkout_on_commit.php -OutFile $ENV:SYSTEMROOT\Temp\commit.txt" || rem
The rem was needed as a "no-op" to prevent the hook from being reported by Tortoise as failing for commits to other projects. The contents of checkout_on_commit.php which cause the project to deploy on the Linux server are:
<?php
`date >> checkout.log`;
`svn sw --non-interactive --no-auth-cache --username project_a_readonly --password trytoguess https://svnserver/svn/GroupA/ProjectA/trunk /app/www/ >> checkout.log`;
?>

In Subversion does not exist a definition like a "Project"...the definition must be done by you. This means Subversion executes that on the change in the repository not on the "Project" base...
You can use the information you get like the repository and the revision number to extract the information you need...You can do that simply by using svnlook to extract the information you need..by calling svnlook with the appropriate parameters.

Related

Revert all files with a specified name

Hi i want to revert all changes to the files with a specific filename in a local repository.
In this case AssemblyInfo.vb, i'm using the TortoiseSVN cli.
I have the following directory structure
Root
Project 1
File1.txt
My Project
AssemblyInfo.vb
Project 2
File2.txt
My Project
AssemblyInfo.vb
Now while standing in Root i run the command svn.exe revert --recursive AssemblyInfo.vb and the output i get is:
Skipped 'AssemblyInfo.vb'
I have tried to add double and single * before the filename with no success, does --recursive/-R work or what am i missing?
svn help revert gives the following output:
revert: Restore pristine working copy state (undo local changes).
usage: revert PATH...
Revert changes in the working copy at or within PATH, and remove
conflict markers as well, if any.
This subcommand does not revert already committed changes.
For information about undoing already committed changes, search
the output of 'svn help merge' for 'undo'.
Valid options:
--targets ARG : pass contents of file ARG as additional args
-R [--recursive] : descend recursively, same as --depth=infinity
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
-q [--quiet] : print nothing, or only summary information
--changelist [--cl] ARG : operate only on members of changelist ARG
Global options:
--username ARG : specify a username ARG
--password ARG : specify a password ARG (caution: on many operating
systems, other users will be able to see this)
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting (default is to prompt
only if standard input is a terminal device)
--force-interactive : do interactive prompting even if standard input
is not a terminal device
--trust-server-cert : deprecated; same as
--trust-server-cert-failures=unknown-ca
--trust-server-cert-failures ARG : with --non-interactive, accept SSL server
certificates with failures; ARG is comma-separated
list of 'unknown-ca' (Unknown Authority),
'cn-mismatch' (Hostname mismatch), 'expired'
(Expired certificate), 'not-yet-valid' (Not yet
valid certificate) and 'other' (all other not
separately classified certificate errors).
--config-dir ARG : read user configuration files from directory ARG
--config-option ARG : set user configuration option in the format:
FILE:SECTION:OPTION=[VALUE]
For example:
servers:global:http-library=serf
If i run svn.exe revert --recursive AssemblyInfo.vb in a directory that directly contains a modified AssemblyInfo.vb it works as intended.
svn revert is designed to help fix mistakes, not cause problems by "helping" users to accidentally or unintentionally remove their local and uncommitted changes.
If you want to revert all the changes in your SVN working copy or in a directory and all its childs, you could run svn revert . -R. But you must not run this command if your working copy has a mixture of valid uncommitted changes that you don't want to lose and the changes that you want to revert to unmodified state.
Reverting local changes is an irreversible operation. Therefore, reverting local changes in SVN working copy via svn revert must be done cautiously. Assume that you are working on a task and haven't yet committed some important changes you've been working on a couple of hours. But at the same time you have some changes in a file or directory that you want to revert. Carelessly running svn revert . -R at the root of working copy will revert all the uncommitted changes in the working copy.
Citing SVNBook | svn revert
svn revert is inherently dangerous, since its entire purpose is to
throw away data—namely, your uncommitted changes. Once you've
reverted, Subversion provides no way to get back those uncommitted
changes.
If you provide no targets to svn revert, it will do nothing. To
protect you from accidentally losing changes in your working copy, svn revert requires you to explicitly provide at least one target.
Now while standing in Root i run the command svn.exe revert
--recursive AssemblyInfo.vb and the output i get is:
svn revert does not work this way. By default, it runs with --depth=empty to ensure that it won't revert more than the user intended. But runningsvn revert with -R is the same as running it with --depth=infinity. Generally speaking, in this particular case --recursive is an alias for --depth=infinity and its purpose is to help users revert all the local modifications (e.g. after invalid merge).
When you run svn revert with --recursive, the tool expects you to specify a path to a directory in your working copy and the operation will revert ALL the changes that are in this directory and its childs. There will be no effect if the command's target is a file.
What you look for is --targets and a bit of scripting. For example, run the following commands in PowerShell console (I'm sure that it could be done more elegantly in PowerShell than in this example):
(dir -Path "files.html" -Recurse -File).FullName | Out-File -Encoding ASCII mytargets.txt
svn revert --targets mytargets.txt
dir is an alias of Get-ChildItem cmdlet in PowerShell. In this case it grabs the list of all files with name files.html and writes the full paths to mytargets.txt file. Then it runs svn revert that reads paths from mytargets.txt and revert local modifications made to the files.
I advise this approach instead of piping the output to svn revert because you can (and should) review the list of items that svn revert will process. This helps you ensure that you won't revert more that you actually intended.
On Linux this can be done using combination of find and xargs commands from findutils:
find -name AssemblyInfo.vb | xargs svn revert
On Windows you can probably install and use Cygwin which contain these utilities.

Create Working Folders using stcmd

I have been trying to write an stcmd that checks out code from a StarTeam repository. Here's what the command looks like:
stcmd co -p "Username:Password#localHost:1024/Store Server/Store Server/USB/sources/$OEM$/$$/Setup/Scripts"
Every time I run this code, I get the following response:
C:\StarTeam\Store Server\USB\sources\$OEM$\$$\Setup\Scripts\osConfig.ps1 (The system cannot find the path specified)
I'm guessing I need to have to create the working folder's location in order for my check-out command to work properly. Is there a way to create the working folders of a repository using stcmd? I know I can do it through StarTeam, but I wanted to see if it's possible to create it through stcmd so it can create the folders on new computers when my code runs.
You haven't said which version you're using, but in 5.4 the command to create working directories is:
stdcmd local-mkdir
so you'd need something like:
stdcmd local-mkdir -p "Username:Password#localHost:1024/Store Server/Store Server/USB/sources/$OEM$/$$/Setup/Scripts"
This is the answer to your question, but I'm not sure it'll be the solution to your problem!
Not sure which version of StarTeam you're using, but in 13.0 at least, there's an option -cwf (checkout working folders) which you can append to the check-out command. if you also want this to checkout subfolders of said working folders, you can also append -is (include subfolders, maybe?). So, try:
stcmd co -p "Username:password#localHost:1024/Store Server/Store Server/USB/sources/$OEM$/$$/Setup/Scripts/" -cwf -is

Git Hook under Windows

I have the following code to checkout in a working directory in the hook post-receive:
#!/bin/sh
git --work-tree=d:/websites/__gitweb --git-dir=d:/_gitrepo.git/ checkout -f
Unfortunately it doesn't seem to work. However, the command does work when I enter just this in the windows command line (cms):
git --work-tree=d:/websites/__gitweb --git-dir=d:/_gitrepo.git/ checkout -f
I have checked the permissions and the executing attributes but nothing.
UPDATE:
I think I'm getting closer. Now I know what the problem is but I don't know why is this happening. The hook is actually being triggered but I receive this message:
remote: Starting copy from repository to work tree...
remote: fatal: Not a git repository: 'd:/_gitrepo.git/'
remote: Finished.
I have tried to change the path of d: to the whole network path but it still doesn't work. If I go to the remote repository and I do a git log, the changes are there and if I run the hook with sh, it works.
Why is it saying that it is not a git repository when clearly it is?
I finally got it working!
This is really weird. I had to type a pwd to see where actually is the batch being located and it showed the hook location on the server. However, in the next line I added a hostname and it showed me my local hostname.
Then I add the whole path just like:
#!/bin/sh
echo "Starting copy from repository to work tree..."
pwd
hostname
git --work-tree=//remotehost/d$/Webseiten/__gitweb --git-dir=//remotehost/d$/_gitr
epo.git checkout -f
echo "Finished."
I hope this solution works for someone
For a shell script (and those hook scripts will be executed as shell, even in Windows, through the msys layer of msysgit), you could use a different sort of path:
#!/bin/sh
git --work-tree=/d/websites/__gitweb --git-dir=/d/_gitrepo.git/ checkout -f
See also other possibilities with "Posix path conversion in MinGW"

How do I execute several git commands in a batch file without terminating after the first command?

I tried to put a series of GIT commands that I always use continuously togeter as batch files so that I don't repeat myself too much. For example, I have this batch file called update_repo_branch.bat to update a local repo and synch a branch with the remote branch:
#echo off
if(%1) == () goto end
if(%2) == () goto end
cd %1
git checkout %2
git fetch origin
git merge oring/%2
:end
Good to be lazy, but what I found is that when a GIT command is finished, it seems to send an exit flag back to terminate whatever is running. Therefore, using a batch file to exectute them all in one go simply doesn't work. Any idea how to work around it?
I'm not sure if this is true for all Windows git packages, but at least some use a git.cmd script as a wrapper around the actual git executables (for example git.exe). So when you're batch file uses a git command, Windows is actually running another batch file.
Unfortunately, when one batch file invokes another, by default it 'jumps' to the invoked batch file, never to return (this is for compatibility with ancient MS-DOS command processors or something).
You can solve this problem in a couple ways:
invoke git in your batch files using the call command to run the git.cmd batch file and return back to yours:
call git checkout %2
call git fetch origin
rem etc...
invoke git in your batch file using the .exe extension explicitly to avoid the git.cmd batch file altogether. For this to work, you might need to make sure that you have your path and other environment variables set the way git.exe expects (that seems to be what git.cmd does in msysgit):
git.exe checkout %2
rem etc...
Assuming you are using msysGit as your Git client you might actually want to use Bash scripts for this. You could place a bash function in your ~/.bashrc (~ is usually your C:\Users\- see here) as follows
update_repo_branch() {
if [ $# != "2" ]; then
echo "Usage: update_repo_branch REPO BRANCH" 1>&2
return 1
fi
cd $1
git checkout $2
git fetch origin
git merge origin/$2
}
You can then run update_repo_branch myrepo cool-branch from the mysysGit shell.
Of course, this won't be accessible from cmd.exe. You will only be able to use it within the msysGit cygwin shell.
As i see from your example you're actually trying to sync your local branch 'branchname' with origin/branchname
For this you don't need any additional scripting, you just have to use git pull instead of sequence git checkout branchname; git fetch origin; git merge origin/branchname
take a look at the docs about tracking branches in git and their benefits.
generally speaking if you have a repo layout like this:
git branch -a
...
master
dev1
dev2
remotes/origin/master
remotes/origin/dev1
remotes/origin/dev2
And your dev1 and dev2 branches are tracking branches for origin/dev1 and origin/dev2 correspondingly then you just need to execute in repository:
git pull
This command will effectively sync up all you local tracking branches with remote ones.
for more see here:
Git pull docs
Git remote branches and tracking branches (Progit book)
Create a notepad file and paste the below content and save with .bat extension.
This script can be use for setting up git first time in a project.
!echo off
git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin <YOUR_REPO_URL>
git push -u origin main
pause

Does hg pull only operate on the current working directory?

I have multiple mercurial repositories and used hg clone to create backups of them on our file server. Now I want to write a batch file that updates them once a day by running hg pull -u on each subdirectory.
I want to keep this backup script as generic as possible, so it should update all backup repositories stored in my H:\BACKUPS\REPOS folder. This is my hgbackup.bat that is stored in the same folder:
for /f "delims=" %%i in ('dir /ad/b') do hg pull -u
The problem: hg pull only seems to operate on the current working directory, there seems to be no switch to specify the target repository for the pull. As I hate Windows Batch Scripting, I want to keep my .bat as simple as possible and avoid cd'ing to the different directories.
Any ideas how I can run hg pull -u on a different directory?
Use the -R-switch:
hg pull -u -R /path/to/repository
See hg -v help pull for all command line options of hg pull (the -v switch tells help to include global options).
Found this question quite a bit later due to a script I was working on for my own computer, and rather than a batch script, I did it in PowerShell (since you mentioned it's on a server, I assumed PS was available). This handles both Subversion and Mercurial repositories:
$path = "c:\users\mattgwagner\Documents\Code"
foreach($fi in get-childitem $path)
{
if(test-path $path\$fi\.svn)
{
"Updating " + $fi + " via Subversion..."
svn update $path\$fi
}
elseif(test-path $path\$fi\.hg)
{
"Updating " + $fi + " via Mercurial..."
hg pull -u -R $path\$fi
}
}

Resources