示例#1
0
 /// <summary>Constructs a VersionData of type FileType.Directory</summary>
 /// <param name="filename">Just the filename, with no preceding directories</param>
 /// <param name="children">The VersionDatas contained in this directory</param>
 public VersionData(string filename, VDKeyedCollection children)
 {
     this.filename = filename;
     this.children = children;
     this.filetype = FileType.Directory;
     this.hash     = GetHash();
 }
示例#2
0
        /// <summary>
        /// Returns a VersionData that contains only those children contained in a changelog
        /// </summary>
        /// <param name="changelog"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public VersionData Trim(Changelog changelog, string prefix = "")
        {
            if (Filetype != FileType.Directory)
            {
                throw new InvalidOperationException("Trim cannot operate on a FileType.File");
            }
            var vdcollection = new VDKeyedCollection();

            foreach (var vd in children)
            {
                string fpath = PrefixFilename(prefix, vd.Filename);
                if (changelog.Added.ContainsKey(fpath) || changelog.Modified.ContainsKey(fpath))
                {
                    if (vd.Filetype == FileType.Directory)
                    {
                        vdcollection.Add(vd.Trim(changelog, fpath));
                    }
                    else
                    {
                        vdcollection.Add(new VersionData(vd.Filename, vd.Data));
                    }
                }
            }
            return(new VersionData(Filename, vdcollection));
        }
示例#3
0
        /// <summary>
        /// Finds objects of the same name, but different hashes
        /// </summary>
        private static void FindModifieds(ChangelogBuilder changelog, string prefix, VDKeyedCollection byName,
                                          VDKeyedCollection otherByName)
        {
            var toRemove = new LinkedList <string>();

            foreach (var otherVD in otherByName)
            {
                //if (byName.ContainsKey(pair.Key))
                if (byName.Contains(otherVD.Filename))
                {
                    VersionData thisVD = byName[otherVD.Filename];
                    if (otherVD.Filetype == thisVD.Filetype)
                    {
                        string fpath = PrefixFilename(prefix, otherVD.Filename);
                        changelog.Modify(fpath, otherVD.Hash);
                        if (otherVD.Filetype == FileType.Directory)
                        {
                            var subchangelog = BuildChangelog(thisVD, otherVD, fpath);
                            changelog.Aggregate(subchangelog);
                        }
                        toRemove.AddLast(otherVD.Filename);
                    }
                }
            }
            foreach (string s in toRemove)
            {
                byName.Remove(s);
                otherByName.Remove(s);
            }
        }
示例#4
0
 /// <summary>
 /// Finds objects of the same hash but different names
 /// </summary>
 private static void FindRenames(ChangelogBuilder changelog, string prefix, VDKeyedCollection byName,
                                 VDKeyedCollection otherByName, Dictionary <string, LinkedList <string> > byHash,
                                 Dictionary <string, LinkedList <string> > otherByHash)
 {
     foreach (var pair in byHash)
     {
         if (otherByHash.ContainsKey(pair.Key))
         {
             var thisll  = pair.Value;
             var otherll = otherByHash[pair.Key];
             while (thisll.Count > 0 && otherll.Count > 0)
             {
                 string thisfile  = thisll.First.Value;
                 string otherfile = otherll.First.Value;
                 byName.Remove(thisfile);
                 otherByName.Remove(otherfile);
                 string thisfpath  = PrefixFilename(prefix, thisfile);
                 string otherfpath = PrefixFilename(prefix, otherfile);
                 changelog.Rename(thisfpath, otherfpath);
                 thisll.RemoveFirst();
                 otherll.RemoveFirst();
             }
         }
     }
 }
示例#5
0
 /// <summary>
 /// Selects all files that were altered in some way (added, modified, removed, or renamed)
 /// </summary>
 /// <param name="thisVD"></param>
 /// <param name="otherVD"></param>
 /// <param name="byName"></param>
 /// <param name="byHash"></param>
 private static void AddAlteredFiles(VDKeyedCollection thisVD, VDKeyedCollection otherVD, VDKeyedCollection
                                     byName, Dictionary <string, LinkedList <string> > byHash)
 {
     foreach (var pair in thisVD)
     {
         string name     = pair.Filename;
         string hash     = pair.Hash;
         bool   contains = false;
         if (otherVD.Contains(name)) //if the file has not been altered
         {
             contains = true;
             if (hash == otherVD[name].Hash)
             {
                 continue;
             }
         }
         if (!byHash.ContainsKey(hash))
         {
             byHash[hash] = new LinkedList <string>();
         }
         if (contains) //prioritize renaming files with no counterpart
         {
             byHash[hash].AddLast(name);
         }
         else
         {
             byHash[hash].AddFirst(name);
         }
         byName.Add(pair);
     }
 }
示例#6
0
        /// <summary>
        /// Recursively builds a Changelog by comparing each directory to its analogue and finding differences
        /// </summary>
        /// <param name="original"></param>
        /// <param name="update"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static ChangelogBuilder BuildChangelog(VersionData original, VersionData update, string prefix = "")
        {
            ChangelogBuilder changelog = new ChangelogBuilder();
            var byHash      = new Dictionary <string, LinkedList <string> >();
            var otherByHash = new Dictionary <string, LinkedList <string> >();
            var byName      = new VDKeyedCollection();
            var otherByName = new VDKeyedCollection();

            if (original == null)
            {
                if (update == null)
                {
                    throw new ArgumentNullException("original and update");
                }
            }
            else if (original.filetype == FileType.File)
            {
                throw new InvalidOperationException("Cannot call GetChangelog on a FileType.File type");
            }
            if (update != null && update.filetype == FileType.File)
            {
                throw new ArgumentException("child must be of type FileType.File");
            }
            if (update == null)
            {
                AggregateRemove(changelog, prefix, original);
                return(changelog);
            }
            if (original == null)
            {
                AggregateAdd(changelog, prefix, update);
                return(changelog);
            }
            AddAlteredFiles(original.children, update.children, byName, byHash);
            AddAlteredFiles(update.children, original.children, otherByName, otherByHash);

            FindRenames(changelog, prefix, byName, otherByName, byHash, otherByHash);
            FindModifieds(changelog, prefix, byName, otherByName);
            FindAddRemoveds(changelog, prefix, byName, otherByName);

            return(changelog);
        }
示例#7
0
        /// <summary>
        /// Converts a DataNode and all descendants to a VersionData
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private VersionData GetDirectoryData(DataNode node)
        {
            VDKeyedCollection children = new VDKeyedCollection();

            foreach (var childNode in node.children)
            {
                if (childNode.data == null)
                {
                    continue;
                }
                if (childNode.data.Filetype == VersionData.FileType.Directory)
                {
                    children.Add(GetDirectoryData(childNode));
                }
                else
                {
                    var vd = childNode.data;
                    children.Add(new VersionData(childNode.filename, vd.Data, vd.Hash));
                }
            }
            return(new VersionData(node.filename, children));
        }
示例#8
0
 /// <summary>
 /// Finds objects that exist in one collection but not the other
 /// </summary>
 private static void FindAddRemoveds(ChangelogBuilder changelog, string prefix, VDKeyedCollection byName,
                                     VDKeyedCollection otherByName)
 {
     foreach (var pair in byName)
     {
         string fpath = PrefixFilename(prefix, pair.Filename);
         changelog.Remove(fpath);
         if (pair.Filetype == FileType.Directory)
         {
             var subchangelog = BuildChangelog(pair, null, fpath);
             changelog.Aggregate(subchangelog);
         }
     }
     foreach (var pair in otherByName)
     {
         string fpath = PrefixFilename(prefix, pair.Filename);
         changelog.Add(fpath, pair.Hash);
         if (pair.Filetype == FileType.Directory)
         {
             var subchangelog = BuildChangelog(null, pair, fpath);
             changelog.Aggregate(subchangelog);
         }
     }
 }
示例#9
0
 /// <summary>Constructs a VersionData of type FileType.Directory</summary>
 /// <param name="filename">Just the filename, with no preceding directories</param>
 /// <param name="children">The VersionDatas contained in this directory</param>
 /// <param name="hash">This VersionData's hash</param>
 public VersionData(string filename, VDKeyedCollection children, string hash)
 {
     this.filename = filename;
     this.children = children;
     this.hash     = hash;
 }