svn offer lot of nice commands that make us able to know what is/did happening in our repository.
i am loking for a command that allows me to list the files that has been modified in a specific revisions (note a range, but a list of some specific revisions).
Exemple:
i'd like to know what are the files that have been modified in the revisions: 624 , 625, 630,631
but i'd like to groupe this by files (if a file has been modified in revision 624 and 630, i'd like it to be whan once)
svn diff --summarize .... can make this but for a range of revision, in my case the range is not possible to have.
PS:
i'm using redmine, so if the solution is there, it'd be nice also.
I don't know of any built-in way to do that in either Subversion or Redmine. I'd suggest writing a small script that repeatedly calls svn diff, and then processes the results.
As an example, here's a quick way to do it via the command line:
echo "255 318 319 320" | perl -p -e 's/ /\n/g' | xargs -I {} svn diff . --summarize -c {} | perl -p -e 's/^...\s*//' | sort | uniq
Related
I need to check if local file is same as remote host file.
The file locations are like below:
File1 at Local machine
./remotehostname/home/a/b/scripts/xyz.cpp
File2 at remote machine
remotehostname:/home/a/b/scripts/xyz.cpp
I intend to compare these 2 files, using the command
diff ./remotehostname/home/a/b/scripts/xyz.cpp remotehostname:/home/a/b/scripts/xyz.cpp
find . -type f | grep -v .svn |xargs -I % diff %
I need to change % to take remotehost and compare the file.
Not sure how to apply sed on %. Or is there a better way to compare such files.
One way could be to save the list of files and then apply sed on that file, but I think there should be an even better way. Also the diff doesnt work on remote hosts, maybe I need to use output of dry rsync?
This can be done with xargs, but I prefer to use while read in bash.
xargs method
find . -type f | grep -v .svn | sed 's/.*/& remotehostname:&/' | xargs -n2 diff
The sed command duplicates the input and makes whatever modifications you need. The xargs then passes the inputs to diff two at a time. This will not work if any filename contain spaces.
bash method
find . -type f | grep -v .svn | while read line; do
diff "$line" "remotehostname:$line"
done
The bash read command reads a line from stdin, places it in the name variable, $line, and returns true. You can then put whatever you like inside the loop, so you get total freedom to rewrite the filename however you need. When the input runs out, read returns false, and the loop exits.
Note that piping things into loops has some interesting side effects that are not relevant here, but might bite you one day.
If you are interested in the actual difference (and not just whether they differ - which rsync is brilliant for telling you) then you can do this using GNU Parallel:
find . -type f | grep -v .svn |
parallel diff {} '<(ssh {= s:./::;s:/.*:: =} cat {= s:([^/]+/){2,2}::;$_=::shell_quote_scalar($_) =})'
s:./::;s:/.*:: = hostname from path
s:([^/]+/){2,2}:: = rest of path
::shell_quote_scalar = \-quote special chars as needed by the shell
GNU Parallel is a general parallelizer and makes is easy to run jobs in parallel on the same machine or on multiple machines you have ssh access to. It can often replace a for loop.
If you have 32 different jobs you want to run on 4 CPUs, a straight forward way to parallelize is to run 8 jobs on each CPU:
GNU Parallel instead spawns a new process when one finishes - keeping the CPUs active and thus saving time:
Installation
If GNU Parallel is not packaged for your distribution, you can do a personal installation, which does not require root access. It can be done in 10 seconds by doing this:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
For other installation options see http://git.savannah.gnu.org/cgit/parallel.git/tree/README
Learn more
See more examples: http://www.gnu.org/software/parallel/man.html
Watch the intro videos: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Walk through the tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html
Sign up for the email list to get support: https://lists.gnu.org/mailman/listinfo/parallel
I have looked at different ways of doing this using diff. The first option I tried is:
p4 diff -sa
Opened files that are different from the revision in the depot, or missing.
Initially I figured that this was a file with write permission bit set that did not exist in the depot. However, I have since learned p4 doesn't use mode bits to track opened/unopened states as I first thought.
Next I figured this option would work:
p4 diff -sl
Every unopened file, along with the status of 'same', 'diff' or 'missin' as compared to its revision in the depot.
This would be okay, except "unopened" is not inclusive of "untracked" files. Although, when I ran this, it produced something quite different that contradicts the documentation; it output pretty much everything that was tracked, but also output everything that wasn't tracked, but flagged them as 'same'. Maybe this means that it hasn't been added and doesn't exist in the depot, so the client is the same as the depot...? In my SVN biased opinion, a rather pointless option.
Then there is the 'opened' option. But this does exactly that. It lists all the files in the depot that have been opened on the client; so not the files modified on the client not yet added.
So is there an option I am missing somewhere, that will provide some valuable answer, like SVN and CVS are able to do with one simple command?
$ svn status
A added
M modified
R deleted
? untracked
L locked
C conflict
Or:
$ cvs -q up -Pd
Okay, looking around and playing with the 'add' command, it seems that a read-only add will output successful message if the file is not currently controlled:
$ p4 add -n -f somefile
//source/somefile#1 - opened for add
I applied this to the following command and pretty much get what I need:
$ find . -type f | while read f ; do p4 add -f -n "$f" | grep -e '- opened for add' >/dev/null && echo "A $f"; done
A ./somefile
Or if you're not bothered about local paths:
$ find . -type f | xargs -l1 p4 add -f -n | grep -e '- opened for add'
//source/somefile#1 - opened for add
Well, there exists "p4 status", which is very similar in both purpose and behavior to "svn status".
For more ideas, see: http://answers.perforce.com/articles/KB_Article/Working-Disconnected-From-The-Perforce-Server
Basically I would like to do:
cleartool find . -version 'version(.../LATEST)' -print
| egrep '\\.[CH]##'
| xargs -I {} grep 'TEXT' {} \;
But version requires a branch name if using .../ and I want to get all branches for the files.
I know you can cheat and get all branches by using -branch '\!attype(dummyname)' but the branch name is only the first step.
I would like to be able to grep all of the LATEST versions on all of the branches and the main for -name '*.[CH]' files in the VOB.
I have made a script to use the above dummyname to get all branches, grep '\\.[CH]##', append LATEST to it and grep that file name for what I am looking for but it is very slow to do it that way.
I confirm this will be slow, and that the -branch '\!attype(dummyname)' seems to be the only way to list all branches, according to IBM cleartool find examples.
I would try first to find all *.ch file versions, and sort that out per branches to isolates the latest. That might be quicker.
I have a legacy CVS repository which shall be migrated to Perforce.
For each module, I need to identify what branches exist in that module.
I just want a list of branch names, no tags.
It must be a command line tool, for scripting reasons.
For example (assuming there is a cvs-list-branches.sh script):
$ ./cvs-list-branches.sh module1
HEAD
dev_foobar
Release_1_2
Release_1_3
$
As a quick hack:) The same stands true for rlog.
cvs log -h | awk -F"[.:]" '/^\t/&&$(NF-1)==0{print $1}' | sort -u
Improved version as per bdevay, hiding irrelevant output and left-aligning the result:
cvs log -h 2>&1 | awk -F"[.:]" '/^\t/&&$(NF-1)==0{print $1}' | awk '{print $1}' | sort -u
You could simply parse log output of cvs log -h. For each file there will be a section named Symbolic names :. All tags listed there that have a revision number that contains a zero as the last but one digit are branches. E.g.:
$ cvs log -h
Rcs file : '/cvsroot/Module/File.pas,v'
Working file : 'File.pas'
Head revision : 1.1
Branch revision :
Locks : strict
Access :
Symbolic names :
1.1 : 'Release-1-0'
1.1.2.4 : 'Release-1-1'
1.1.0.2 : 'Maintenance-BRANCH'
Keyword substitution : 'kv'
Total revisions : 5
Selected revisions : 0
Description :
===============================================
In this example Maintenance-BRANCH is clearly a branch because its revision number is listed as 1.1.0.2. This is also sometimes called a magic branch revision number.
This will bring up tags too, but tags and branches are basically the same in CVS.
$cvs.exe rlog -h -l -b module1
I have a small collection of "handy" korn shell functions one of which fetches tags for a given file. I've made a quick attempt to adapt it to do what you want. It simply does some seding/greping of the (r)log output and lists versions which have ".0." in them (which indicates that it's a branch tag):
get_branch_tags()
{
typeset FILE_PATH=$1
TEMP_TAGS_INFO=/tmp/cvsinfo$$
/usr/local/bin/cvs rlog $FILE_PATH 1>${TEMP_TAGS_INFO} 2>/dev/null
TEMPTAGS=`sed -n '/symbolic names:/,/keyword substitution:/p' ${TEMP_TAGS_INFO} | grep "\.0\." | cut -d: -f1 | awk '{print $1}'`
TAGS=`echo $TEMPTAGS | tr ' ' '/'`
echo ${TAGS:-NONE}
rm -Rf $TEMP_TAGS_INFO 2>/dev/null 1>&2
}
with Wincvs (Gui client for windows) this is trivial, a right click will give you any branches and tags the files have.
Trough a shell you may use cvs log -h -l module.
Check for the very first file created and committed in the repository. Open the file in server which will list all the Tags and Branches together
I have made a bunch of changes to a number of files in a project. Every commit (usually at the file level) was accompanied by a comment of what was changed.
Is there a way to get a list from CVS of these comments on changes since the last tagged version?
Bonus if I can do this via the eclipse CVS plugin.
UPDATE: I'd love to accept an answer here, but unfortunately none of the answers are what I am looking for. Frankly I don' think it is actually possible, which is a pity really as this could be a great way to create a change list between versions (Assuming all commits are made at a sensible granularity and contain meaningful comments).
I think
cvs -q log -SN -rtag1:::tag2
or
cvs -q log -SN -dfromdate<todate
will do what you want. This lists all the versions and comments for all changes made between the two tags or dates, only for files that have changed. In the tag case, the three colons exclude the comments for the first tag. See cvs -H log for more information.
The options for the cvs log command are available here. Specifically, to get all the commits since a specific tag (lets call it VERSION_1_0)
cvs log -rVERSION_1_0:
If your goal is to have a command that works without having to know the name of the last tag I believe you will need to write a script that grabs the log for the current branch, parses through to find the tag, then issues the log command against that tag, but I migrated everything off of CVS quite a while ago, so my memory might be a bit rusty.
If you want to get a quick result on a single file, the cvs log command is good. If you want something more comprehensive, the best tool I've found for this is a perl script called cvs2cl.pl. This can generate a change list in several different formats. It has many different options, but I've used the tag-to-tag options like this:
cvs2cl.pl --delta dev_release_1_2_3:dev_release_1_6_8
or
cvs2cl.pl --delta dev_release_1_2_3:HEAD
I have also done comparisons using dates with the same tool.
I know you have already "solved" your problem, but I had the same problem and here is how I quickly got all of the comments out of cvs from a given revision until the latest:
$ mkdir ~/repo
$ cd ~/repo
$ mkdir cvs
$ cd cvs
$ scp -pr geek#avoid.cvs.org:/cvs/CVSROOT .
$ mkdir -p my/favorite
$ cd my/favorite
$ scp -pr geek#avoid.cvs.org:/cvs/my/favorite/project .
$ cd ~/repo
$ mkdir -p ~/repo/svn/my/favorite/project
$ cvs2svn -s ~/repo/svn/my/favorite/project/src ~/repo/cvs/my/favorite/project/src
$ mkdir ~/work
$ cd ~/work
$ svn checkout file:///home/geek/repo/svn/my/favorite/project/src/trunk ./src
$ cd src
$ # get the comments made from revision 5 until today
$ svn log -r 5:HEAD
$ # get the comments made from 2010-07-03 until today
$ svn log -r {2010-07-03}:HEAD
The basic idea is to just use svn or git instead of cvs :-)
And that can be done by converting the cvs repo to svn or git using cvs2svn or cvs2git, which we should be doing anyway. It got my my answer within about three minutes because I had a small repository.
Hope that helps.
Something like this
cvs -q log -NS -rVERSION_3_0::HEAD
Where you probably want to pipe the output into egrep to filter out the stuff you don't want to see. I've used this:
cvs -q log -NS -rVERSION_3_0::HEAD | egrep -v "RCS file: |revision |date:|Working file:|head:|branch:|locks:|access list:|keyword substitution:|total revisions: |============|-------------"