BuildRevisionList AddRevision(...)

May 29, 2012 at 1:08 AM

Hello (John :-),

I'm looking at vssmigrate-47996.  At line 466 there is an AddRevision(version,true) if the item has been deleted.  Should that AddRevision(version, true) be followed by a continue; ?  Otherwise it looks like in those rare cases of deleted items the revision would be added twice.

I'm not a C# developer (I work in Java, C, C++, PHP mostly) nor do I understand the code here, so I'd be glad to be wrong.

Gerald

May 29, 2012 at 8:21 AM
Edited May 29, 2012 at 8:25 AM

Hi Gerald!

I'm also not a C# developer, I actually work with C++ all day. every day (well, with the occasional detour into Perl :-), but I was able (after a lot of trial, error, and banging my head against a wall) to figure out at least part of what was happening .-)

I compared the code I have now against the original, and found that I made the following changes in BuildRevisionList:

  1. Check for, and ignore, temporary items created by VSS itself;
  2. Use the value of "Version.VSSItem.Deleted" as the 2nd parameter value in the call to AddRevision.

The modified method follows:

 

private static void BuildRevisionList(IVSSItem item)
{
   IVSSVersions versions = item.get_Versions();

   // TODO: If a file is deleted after having been added to the revisions list, we need to ensure that
   // it *only* appears in the relevant tag/label and not in the trunk.
   foreach (IVSSVersion version in versions)
   {
      try
      {
         // Comment check added because, for some reason, several temporary (and deleted) files appear here with the
         // .Deleted property == FALSE.
         if (version.Comment.Contains("Temporary file created by Microsoft Visual Studio"))
            continue;

         // Normal file/folder/label
         AddRevision(version, version.VSSItem.Deleted);
      }
      catch (COMException ex)
      {
         switch ((uint)ex.ErrorCode)
         {
            case 0x80040000: //version is corrupted and unavailable
               searchLog.WarnFormat(
                  "Skipping version due to corruption {0} in file {1} [cannot read resource]",
                  version.VersionNumber, item.Spec);
               continue;
            case 0x8004D68F: //file not found
               searchLog.WarnFormat("Skipping version due to corruption {0} in file {1} [file not found]",
                               version.VersionNumber, item.Spec);
               continue;

            // 2011-10-31 JCU: Prevent the import process from crashing on error 0x80004005
            // This error is thrown when an attempt is made to retrieve the history of a deleted
            // item, but the history item is simply a label.

            case 0x80004005: //version is (probably!) a label, but the original item has been deleted.
               if (version.VSSItem.Deleted)
               {
                  searchLog.WarnFormat("Skipping version (LABEL) because this item has been deleted.");
                  continue;
               }

               // If the item was NOT deleted, the error probably indicates some other problem. Pass it back to the user.
               goto default;

            default:
               migrateLog.ErrorFormat("Method: BuildRevisionList");
               throw;
         }
      }
   }
}

I also made a tiny change in AddRevision itself, to resolve a problem I encountered with pinned versions. The original and modified code follows:

//[Original]
//if pinned add to a special (and always last) revision
if (version.VSSItem.IsPinned)
{
   if (!revisions.ContainsKey(pinProps))  //if there is no pinprop revision, add one ...
   {
      revisions.Add(pinProps, new Dictionary<string, VssFileVersion>(StringComparer.CurrentCultureIgnoreCase) { { file.Spec, file } });
   }
   else //else add file to pinprop revision
   {
      revisions[pinProps].Add(file.Spec, file);
   }
}


//[Modified]
//if pinned add to a special (and always last) revision
if (version.VSSItem.IsPinned)
{
   if (!revisions.ContainsKey(pinProps))  //if there is no pinprop revision, add one ...
   {
      revisions.Add(pinProps, new Dictionary<string, VssFileVersion>(StringComparer.CurrentCultureIgnoreCase) { { file.Spec, file } });
   }
   else //else add file to pinprop revision, but only if no later pinned version already exists.
   {
      if (!revisions[pinProps].ContainsKey(file.Spec))
         revisions[pinProps].Add(file.Spec, file);
   }
}

Hope this helps!

 

John

May 30, 2012 at 12:50 AM

Thank you.  I saw the Skipping Version (LABEL) patch in another forum post (by you) and had applied that since it was biting me.  I ran across the pinned version issue on my own and patched it similar to yours.  I think not exactly the same way though (I was just avoiding the key already exists issue, not actually understanding about later pinned versions).

I'll be comparing svn and vss and if they don't match I'll try your patches :-).

Many thanks.

Gerald