Super! Thanks again Dmitry! -Aravinda
On Wed, Sep 4, 2013 at 11:09 AM, Dmitry Pavlenko <pavle...@tmatesoft.com>wrote: > Hello again, Aravinda! > Now I can confirm that you can replace multiple SVNRepository#getDir calls > with a single > SVNRepository#getMergeInfo call which is supported by SVN server since > version 1.5 (for older > servers SVNKit will just generate multiple requests, so you don't have to > bother about the server > version). So you can get all information you need in 2 or 3 requests, as I > wrote yesterday. > > -- > Dmitry Pavlenko, > TMate Software, > http://subgit.com/ - git-svn bridge > > > Hello Aravinda! > > First of all I'd like to recommend you to use new SVNKit API, based on > > SvnOperationFactory class. In the future we will add feature only to this > > API, old SVNXXXClient-based API will be still operational, but won't have > > newer features. If you look at how SVNDiffClient#doDiffStatus is > > implemented you'll see that it's implemented via SvnOperationFactory, but > > it's better to use SvnOperationFactory in your application directly. > > > > The only way to understand if the file was merged or not is to track > > svn:mergeinfo (SVNProperty.MERGE_INFO) changes between those revisions. > > This property can be changed on that certain file or on some of parent > > directory, if the whole directory was merged. Note that svn:mergeinfo > > property value consists of ranges that can be inheritable or > > non-inheritable. If non- inheritable range was changed on some parent > > directory, the file shouldn't be considerd as merged. > > > > Unfortunately doDiffStatus and its new analog SvnDiffSummarize allow to > > tell you that some properties were modified, but don't tell you which > > properties and how they were modified. As a solution, you can use > > low-level SVNKit API, based on SVNRepository class. To get all changes in > > one SVN request use SVNRepository#diff method to get diff between > > revisions in a form of ISVNEditor calls (set getContents=false in order > to > > tell the server not to send you the content of the files). Pass your own > > implementation of ISVNEditor to collect new svn:mergeinfo values on > > directories on which it was changed. For those directories, where > > svn:mergeinfo was changed, call SVNRepository#getDir to get old > > svn:mergeinfo values. One more note: some servers for http(s) protocols > > don't send properties changes if getContents=false, but they send you a > > change of a virtual property svn:BOGOSITY. If your > > ISVNEditor#changeDirProperty is called with that property, you have to > > perform a separate SVNRepository#getDir request to get new svn:mergeinfo > > property (note: you can't do that directly using the same SVNRepository > > object, see > > http://vcs.atspace.co.uk/2012/09/21/are-svnkit-methods-reenterable/ for > > details, you can use another SVNRepository object or better perform > > SVNRepository#getDir after SVNRepository#diff is finished). > > > > Once you get old and new svn:mergeinfo property values for directories > and > > files where it was changed, you can calculate which ranges were changes > in > > those values. To do that use SVNMergeInfoUtil#parseMergeInfo to convert > > svn:mergeinfo values to Map:s and SVNMergeInfoUtil#diffMergeInfo to find > > difference between those maps. Finally check those ranges: the path is > > merged if either > > a) the difference contains changed ranges for that path > > b) the difference contains any inheritable range (use > > SVNMergeRange#isInheritable method) for one of its parent paths > > (SVNPathUtil will help you a lot here). > > > > Some notes: you can reuse the same SVNRepository#diff to understand if > any > > files/directories were changed, so no separate diffClient.doDiffStatus > > request is required. Instead of ISVNReporterBaton object for > > SVNRepository#diff method use the following implementation: > > > > new ISVNReporterBaton() { > > @Override > > public void report(ISVNReporter reporter) throws > SVNException { > > reporter.setPath("", null, start, SVNDepth.INFINITY, > > false); reporter.finishReport(); > > } > > } > > > > The method described above may seem a bit tricky but to my opinion it's > the > > fastest way to achieve your goals, because it requires just 1+N requests > > for all protocols except http(s) and 1+2N requests for http(s) (where N > is > > the number of directories with changed svn:mergeinfo, usually 0 or 1): > one > > SVNRepository#diff and N times SVNRepository#getDir to get old > > svn:mergeinfo values (and N requests by SVNRepository#getDir to get new > > svn:mergeinfo, if you receive svn:BOGOSITY). And one more advantage of > > SVNRepository#diff approach is that you don't have to receive file > content > > from the server. > > > > Maybe those N requests for svn:mergeinfo can be replaced with a single > > SVNRepository#getMergeInfo request, but I'm not sure, I should consult > > with my colleagues about that. But if this is true, you can get all > > information you need in 2 or 3(for http(s)) requests, that's a very good > > result. > > > > SVNStatusType.MERGED has another purpose, and you'll never receive it > when > > calling doDiffStatus > > > > Hope this helps. > > -- > > Dmitry Pavlenko, > > TMate Software, > > http://subgit.com/ - git-svn bridge > > > > > Hi folks, > > > > > > I am currently capturing the changes that happened to files in the > > > following approach. Basically, based on the SVNSTatusType, I am filling > > > up 3 lists that hold added, changed and deleted files between 2 > > > revisions under a repo URL. > > > > > > diffClient.doDiffStatus(url, start, url, end, SVNDepth.INFINITY, > false, > > > > > > new ISVNDiffStatusHandler() { > > > > > > @Override > > > public void handleDiffStatus(final SVNDiffStatus > > > > > > diffStatus) throws SVNException { > > > > > > if (diffStatus.getKind() == SVNNodeKind.FILE) { > > > > > > String ext = > > > > > > getFileExtension(diffStatus.getURL()); > > > > > > if (extensions.contains(ext)) { > > > > > > SVNStatusType status = > > > > > > diffStatus.getModificationType(); > > > > > > if (status == > SVNStatusType.STATUS_ADDED) > > > { > > > > > > addedFiles.add(diffStatus.getURL().toDecodedString()); > > > > > > } else if (status == > > > > > > SVNStatusType.STATUS_DELETED) { > > > > > > deletedFiles.add(diffStatus.getURL().toDecodedString()); > > > > > > } else if (status == > > > > > > SVNStatusType.STATUS_MODIFIED) { > > > > > > changedFiles.add(diffStatus.getURL().toDecodedString()); > > > > > > } > > > > > > } > > > > > > } > > > > > > } > > > > > > }); > > > > > > Now, I want to selectively add only the files that got affected during > > > direct check-ins, and not ones that came in during merge operations > (coz > > > I felt that merged content is also getting counted. I wasn't sure if it > > > was coz things were really merged or if it was merged in a > non-svn-merge > > > fashion by some file merge and direct checkins). > > > > > > How do I capture whether an addition, change or a deletion is a result > of > > > a merge or not following this approach? I see a property 'MERGED' as > > > well in SVNStatusType, and wondering if the above approach already has > > > take care of it. > > > > > > -Aravinda >