Menu

Merge of Subvserion Folder tree

2010-03-25
2012-09-23
  • Ievgenii Nazaruk

    Hi all,

    I have two directories two merge, let's call them A and B. They are both under
    Subversion control (i.e. have .svn folder all over the place). A is from
    branch_a, and B is from branch_b (i.e. their .svn folder are different).

    Merging scenario is simple. A is newer and we should just copy over all file
    from A into B. But the caveat is that all .svn folders should be left from B.
    That is all subversion info in B should be not be overwritten or deleted.

    To make an example:
    RootFolder(a) RootFolder (b) RootFolder(b, expected after merge)
    .svn (a) .svn (b) .svn (b)
    -file1 (a) -file1 (b) - file1 (a)
    -folder (a) -folder (b) - folder (a)
    --.svn (a) --.svn (b) -- .svn (b)
    -- file2 (a) -- file2 (b) -- file2 (a)

    So, basically I expect to have all non-ignored files to be copied over into B.
    And all ignored filed (from anti-pattern) to left intact in folder B.

    The actual result after using kdiff3 is that folder B is copied and renamed as
    B.orig (or just deleted if backups are disabled). And then A is copied as B
    with all ignored files removed.

    I just wanted to know whether such scenario is supported?

     
  • Ievgenii Nazaruk

    RootFolder(a)            RootFolder (b)                RootFolder(b, expected after merge)
    .svn (a)                        .svn (b)                             .svn (b)
    -file1 (a)                      -file1 (b)                            -file1 (a)
    -folder (a)                   -folder (b)                         - folder (a)
    --.svn (a)                    --.svn (b)                           -- .svn (b)
    -- file2 (a)                   -- file2 (b)                         -- file2 (a)
    
     
  • Joachim Eibl

    Joachim Eibl - 2010-03-25

    Hi,
    If you choose "A" for everything I can reproduce the problem.

    For the moment, if in folder A the files are really newer, then you can try
    this:
    First set "Copy newer instead of merging" in the directory settings.
    And specify ".svn" as one of the directory antipatterns.
    Then choose Directory->Rescan.
    ".svn" folders should not be listed, for all files the newer ones should be
    chosen and for folders the operation would be "Merge". Then the folder is not
    deleted or renamed.

    If you compile KDiff3 yourself, you can apply the patch below, which should
    fix the problem.
    I also checked it in into the svn-repository:
    http://kdiff3.svn.sourceforge.net/viewvc/kdiff3/trunk/kdiff3/src-QT4/director
    ymergewindow.cpp?revision=100

    Joachim

    --- directorymergewindow.cpp (Revision 99)
    +++ directorymergewindow.cpp (Arbeitskopie)
    @@ -2498,9 +2498,11 @@
    bool DirectoryMergeWindow::copyFLD( const QString& srcName, const QString&
    destName )
    {
    if ( srcName == destName )
    return true;

    • if ( FileAccess(destName, true).exists() )
    • FileAccess fi( srcName );
    • FileAccess faDest(destName, true);
    • if ( faDest.exists() && !( fi.isDir() && faDest.isDir() && (fi.isSymLink()==faDest.isSymLink())) )
      {
      bool bSuccess = deleteFLD( destName, m_pOptions->m_bDmCreateBakFiles );
      if ( !bSuccess )
      @@ -2511,7 +2513,6 @@
      }
      }

    • FileAccess fi( srcName );

    if ( fi.isSymLink() && ((fi.isDir() && !m_bFollowDirLinks) || (!fi.isDir() &&
    !m_bFollowFileLinks)) )
    {
    @@ -2539,8 +2540,13 @@

    if ( fi.isDir() )
    {

    • bool bSuccess = makeDir( destName );
    • return bSuccess;
    • if ( faDest.exists() )
    • return true;
    • else
    • {
    • bool bSuccess = makeDir( destName );
    • return bSuccess;
    • }
      }
     
  • Ievgenii Nazaruk

    Hi,

    Thanks for quick reply.

    I tried your fix and it works as expected on my example. But infeasible to use
    "Copy newer instead of merging" when having a large directory tree in which
    some subfolders should be copied (i.e. merged with "Copy newer instead of
    merging" enabled) and some should merged (i.e. merged with "Copy newer instead
    of merging" disabled).

    I guess this would be a feature request then. You could probably add a
    checkbox for a special Copy operation. I.e. all copy operations on folders
    will have a special algorithm (described below). Let's call this "Filtered
    Copy" option so I can reference to it ("Filtered" because only files that
    filtered-in with both pattern and anti-pattern are copied, all filtered-out
    files are ignored and just left intact).

    So here is algorithm:

    If "Filtered Copy" is enabled, each directory copy operation goes like this:

    1) Create backup copy of destination (if enabled)

    //Files
    2) Each non-ignored file should be deleted from destination folder
    Ignored files should be left in destination folder without any modifications.

    3) Copy all non-ignored files from source folder into destination folder.

    //Directories
    4) Make a recursive "Filtered Copy" on each non-ignored subfolder.
    (if folder didn't exist in destination, then create it before call "Filtered
    Copy" on this folder).

    I made a quick fix myself to test this algorithm on my larger tree structure.
    It's just a draft code to describe an idea
    It would make more sense to introduce a special filderedCopyFLD (...) function
    for this ( I skipped step 2 - deleting files from destination folder in
    implementation).

    Let me know if you need example of folder tree structure which would benefit
    from this option.

    Index: kdiff3-svn/kdiff3/src-QT4/directorymergewindow.cpp
    ===================================================================
    --- kdiff3-svn/kdiff3/src-QT4/directorymergewindow.cpp  (revision 100)
    +++ kdiff3-svn/kdiff3/src-QT4/directorymergewindow.cpp  (working copy)
    @@ -2500,24 +2500,23 @@
        if ( srcName == destName )
           return true;
    
    +//   if ( FileAccess(destName, true).exists() )
    +//   {
    +//      bool bSuccess = copyFLD(destName, destName + QString(".orig"));
    +//      if ( !bSuccess )
    +//      {                                                                                                                                                                                                     
    +//         m_pStatusInfo->addText(i18n("Error: copy( %1 -> %2 ) failed."                                                                                                                                      
    +//            "Deleting existing destination failed.",srcName,destName));                                                                                                                                     
    +//         return false;                                                                                                                                                                                      
    +//      }                                                                                                                                                                                                     
    +//   }
    
    +                                                                                                                                                                                                              
        FileAccess fi( srcName );                                                                                                                                                                                  
    -   FileAccess faDest(destName, true);                                                                                                                                                                         
    -   if ( faDest.exists() && !( fi.isDir() && faDest.isDir() && (fi.isSymLink()==faDest.isSymLink())) )                                                                                                         
    -   {                                                                                                                                                                                                          
    -      bool bSuccess = deleteFLD( destName, m_pOptions->m_bDmCreateBakFiles );                                                                                                                                 
    -      if ( !bSuccess )                                                                                                                                                                                        
    -      {                                                                                                                                                                                                       
    -         m_pStatusInfo->addText(i18n("Error: copy( %1 -> %2 ) failed."
    -            "Deleting existing destination failed.",srcName,destName));
    -         return false;
    -      }
    -   }
    
    -
        if ( fi.isSymLink() && ((fi.isDir() && !m_bFollowDirLinks)  ||  (!fi.isDir() && !m_bFollowFileLinks)) )
        {
           m_pStatusInfo->addText(i18n("copyLink( %1 -> %2 )",srcName,destName));
    -#if defined(_WIN32) || defined(Q_OS_OS2)
    +#ifdef _WIN32
           // What are links?
     #else
           if ( m_bSimulatedMergeStarted )
    @@ -2540,13 +2539,8 @@
    
        if ( fi.isDir() )
        {
    
    -      if ( faDest.exists() )
    -        return true;
    -      else
    -      {
    -         bool bSuccess = makeDir( destName );
    -         return bSuccess;
    -      }
    +      bool bSuccess = makeDir( destName );
    +      return bSuccess;
        }
    
        int pos=destName.lastIndexOf('/');
    @@ -2566,8 +2560,47 @@
        }
    
        FileAccess faSrc ( srcName );
    
    -   bool bSuccess = faSrc.copyFile( destName );
    -   if (! bSuccess ) m_pStatusInfo->addText( faSrc.getStatusText() );
    +
    +   bool bSuccess = false;
    +   if(!fi.isDir())
    +   {
    +     bSuccess = faSrc.copyFile( destName );
    +     if (! bSuccess ) m_pStatusInfo->addText( faSrc.getStatusText() );
    +   }
    +   else
    +   {
    +     t_DirectoryList dirList;
    +     faSrc.listDir(&dirList, false, m_pOptions->m_bDmFindHidden,
    +         m_pOptions->m_DmFilePattern, m_pOptions->m_DmFileAntiPattern,
    +         m_pOptions->m_DmDirAntiPattern,
    +         m_pOptions->m_bDmFollowDirLinks,
    +         m_pOptions->m_bDmUseCvsIgnore);
    +
    +     t_DirectoryList::iterator dirIter;
    +     for(dirIter = dirList.begin(); dirIter != dirList.end(); dirIter++)
    +     {
    +       QString destUrl = destUrl + dirIter->fileName();
    +
    +       if(!dirIter->isDir())
    +       {
    +         bSuccess = dirIter->copyFile(destUrl);
    +         if (! bSuccess )
    +         {
    +           m_pStatusInfo->addText( dirIter->getStatusText() );
    +           break;
    +         }
    +       }
    +       else
    +       {
    +          bSuccess = copyFLD(dirIter->filePath(), destUrl);
    +          if (! bSuccess )
    +          {
    +            break;
    +          }
    +       }
    +     }
    +   }
    +
        return bSuccess;
     }
    
     
  • Joachim Eibl

    Joachim Eibl - 2010-03-26

    Hi,
    I can understand that for a big directory you would like to choose one source
    for certain folders and "Copy newer" for others.
    If "Copy Newer" is active you can still override this setting on a per folder
    base manually.
    I don't understand how the filtered copy would help, unless there is another
    bug, for KDiff3 should only work on the filtered files anyway. Could you
    please specify an example here? Or could you please give more info on what you
    expected and what happened instead?
    Joachim

     
  • Ievgenii Nazaruk

    Hi

    I probably missed something. I did some more tests with older version of
    kdiff3 and with current trunk version. It seems to work as I expected even
    with "copy newer" disabled - all .svn folders are preserved without changes in
    target folder.

    Thanks a lot for your help.

     
  • Ievgenii Nazaruk

    p.s. Forgot to mention, that everything works fine in the newest version of
    trunk. But older version did actually misbehave.

     
  • Joachim Eibl

    Joachim Eibl - 2010-03-29

    Thank you for your feedback.
    Joachim

     
MongoDB Logo MongoDB