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
>

Reply via email to