/// <summary>
		/// Initializes a new instance.
		/// </summary>
		public ChangesetSummary(Changeset changeset)
		{
			Id = changeset.ChangesetId;
			User = changeset.Committer;
			UserDisplay = changeset.CommitterDisplayName;
			Date = changeset.CreationDate.ToUniversalTime();
		}
示例#2
0
        private static Changeset MapChangeset(TfsChangeset dataModel, Branch branch)
        {
            var changeset = MapChangeset(dataModel);

            changeset.Branch = branch;
            return(changeset);
        }
 public ChangesetVisitEventArgs(Changeset changeset, IEnumerable<string> localizedServerItems, Workspace workspace)
 {
     LocalizedServerItems = localizedServerItems;
     Workspace = workspace;
     Changeset = changeset;
     Committer = changeset.Committer;
 }
示例#4
0
        public bool IsFilterPassed(Changeset changeset)
        {
            if (WorkItemTypes != null
                && WorkItemTypes.Count > 0
                && changeset.WorkItems.Any(wi => WorkItemTypes.Any(t => t == wi.Type.Name)))
                    return true;

            return false;
        }
示例#5
0
 public ChangesetModel(Changeset changeset)
 {
     ID = changeset.ChangesetId;
     Comment = changeset.Comment;
     CreationDate = changeset.CreationDate;
     WorkItems =  new List<WorkItemModel>();
     foreach (var workItem in changeset.WorkItems)
         WorkItems.Add(new WorkItemModel(workItem));
 }
        internal ChangesetViewModel(TeamProject project, Changeset changeset, IChangeInfo info)
        {
            this.Project = project;
            if (changeset == null)
                throw new ArgumentNullException("changeset");

            this.Info = info;
            this.Changeset = changeset;
        }
 private string GetAssociatedWorkItems( Changeset changeset )
 {
     List<string> workItemIds = new List<string>();
     foreach( WorkItem workItem in changeset.WorkItems )
     {
         workItemIds.Add( workItem.Id.ToString() );
     }
     return string.Join( ",", workItemIds.ToArray() );
 }
        private static bool HasWorkItem(Changeset lastChangeset)
        {
            if (lastChangeset == null)
                return false;

            if (lastChangeset.WorkItems == null || lastChangeset.WorkItems.Length == 0)
                return false;

            return true;
        }
 private void FormCommonAuthenticationAndRepositoryParameters(Changeset changeset, string commiterName, StringBuilder sb)
 {
     sb.AppendFormat(@" --repository-url=""{0}""", config.SvnServer);
     sb.AppendFormat(@" --server=""{0}""", config.ReviewBoardServer);
     sb.AppendFormat(@" --username=""{0}""", config.ReviewBoardUserName);
     sb.AppendFormat(@" --password=""{0}""", config.ReviewBoardPassword);
     sb.AppendFormat(@" --submit-as=""{0}""",
                     users.Any(u => u.Equals(commiterName, StringComparison.InvariantCultureIgnoreCase)) ? commiterName : config.NotExistentUserName);
     sb.AppendFormat(@" --revision-range=""{0}:{1}""", changeset.ChangesetId - 1, changeset.ChangesetId);
 }
示例#10
0
 private static int CompareChangesets(Changeset c1, Changeset c2)
 {
     long t1 = ChangesetCommitTime(c1), t2 = ChangesetCommitTime(c2);
     if (t1 == t2)
         return 0;
     else if (t1 < t2)
         return -1;
     else
         return 1;
 }
示例#11
0
        private static FileChangeInfo CreateFileChange(Changeset changesetItem, Change changeItem)
        {
            var newInfo = new FileChangeInfo();

            newInfo.ChangesetId = changesetItem.ChangesetId;
            newInfo.ChangeType = changeItem.ChangeType;
            newInfo.Member = changesetItem.Committer;
            newInfo.ItemPath = changeItem.Item.ServerItem;

            return newInfo;
        }
示例#12
0
 private static HistoryCsvEntry BuildHistoryCsvEntry(Changeset change)
 {
     var entry = new HistoryCsvEntry
                 {
                     Date = change.CreationDate,
                     ChangesetId = change.ChangesetId,
                     Committer = change.Committer,
                     Comment = change.Comment.Trim().TrimEnd(',').Replace('"', ' '),
                     WorkItems = change.WorkItems.Aggregate(string.Empty, (current, workItem) => current + string.Format("{0}: {1}, ", workItem.Id, workItem.Title)).Trim().TrimEnd(',').Replace('"', ' ')
                 };
     return entry;
 }
 public TfsCheckin(Changeset source, string serverId, string teamProjectCollection, string folderId, string folderPath)
 {
     Comment = source.Comment;
     Committer = GetFullName(source.Committer);
     CommitterDomainName = source.Committer;
     CreationDate = source.CreationDate;
     ChangesetId = source.ChangesetId;
     Owner = source.Owner;
     ServerId = serverId;
     TeamProjectCollection = teamProjectCollection;
     FolderId = folderId;
     FolderPath = folderPath;
 }
示例#14
0
        protected ChangesetViewModel ToChangesetViewModel(Changeset tfsChangeset, ChangesetService changesetService)
        {
            var changesetViewModel = new ChangesetViewModel
            {
                ChangesetId = tfsChangeset.ChangesetId,
                Comment = tfsChangeset.Comment,
                Branches = changesetService.GetAssociatedBranches(tfsChangeset.ChangesetId)
                    .Select(i => i.Item)
                    .ToList()
            };

            return changesetViewModel;
        }
示例#15
0
 private static Changeset MapChangeset(TfsChangeset dataModel)
 {
     // todo: implement mapper layer
     return(new Changeset
     {
         Id = dataModel.ChangesetId,
         CreationDate = dataModel.CreationDate,
         CommittedBy = new Identity
         {
             UniqueName = dataModel.Committer ?? dataModel.Owner,
             DisplayName = dataModel.CommitterDisplayName ?? dataModel.OwnerDisplayName
         },
         WorkItems = dataModel.WorkItems != null?dataModel.WorkItems.OrderBy(o => o.Id).Select(TfsTrackingDataAccess.MapWorkItem) : null
     });
 }
示例#16
0
        protected ChangesetViewModel ToChangesetViewModel(Changeset tfsChangeset, ChangesetService changesetService)
        {
            var branches = changesetService.GetAssociatedBranches(tfsChangeset.ChangesetId)
                .Select(i => i.Item)
                .ToList();
            var changesetViewModel = new ChangesetViewModel
            {
                ChangesetId = tfsChangeset.ChangesetId,
                Comment = tfsChangeset.Comment,
                Branches = branches,
                DisplayBranchName = BranchHelper.GetDisplayBranchName(branches, _settings.BranchNameMatches)
            };

            return changesetViewModel;
        }
 private void Merge( ChangeHistoryDataSet versions, Changeset changeset )
 {
     foreach( Change change in changeset.Changes )
     {
         if( change.Item.ItemType == ItemType.File )
         {
             versions.Add( change.Item.ItemId,
                 change.Item.ServerItem,
                 changeset.ChangesetId,
                 clientHelper.LatestVersion,
                 changeset.CreationDate,
                 changeset.Committer,
                 BuildComment( changeset, change ) );
         }
     }
 }
示例#18
0
        private static void SetLastWorkItem(ITeamExplorer teamExplorer, Changeset changeset)
        {
            var workItemId = GetAssociatedWorkItemId(changeset);

            if (workItemId == 0)
                return;

            var pendingChangesPage = (TeamExplorerPageBase)teamExplorer.NavigateToPage(new Guid(TeamExplorerPageIds.PendingChanges), null);
            var model = (IPendingCheckin)pendingChangesPage.Model;

            var modelType = model.GetType();
            var method = modelType.GetMethod("AddWorkItemsByIdAsync",
                BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
            var workItemsIdsArray = new[] { workItemId };
            method.Invoke(model, new object[] { workItemsIdsArray, 1 /* Add */ });

        }
示例#19
0
        public Changeset QueryChangeset(int changesetId, bool includeChanges,
                                        bool generateDownloadUrls)
        {
            Message msg = new Message(GetWebRequest(new Uri(Url)), "QueryChangeset");

            msg.Body.WriteElementString("changesetId", Convert.ToString(changesetId));
            msg.Body.WriteElementString("includeChanges", Convert.ToString(includeChanges).ToLower());
            msg.Body.WriteElementString("generateDownloadUrls", Convert.ToString(generateDownloadUrls).ToLower());

            Changeset changeset = null;

            using (HttpWebResponse response = Invoke(msg))
            {
                XmlReader results = msg.ResponseReader(response);
                changeset = Changeset.FromXml(this, results);
            }

            return(changeset);
        }
示例#20
0
        private static long ChangesetCommitTime(Changeset item)
        {
            // Some changesets in our projects do not have comments and
            // this causes an InvalidOperationException. So we check if
            // item.Comment is valid before performing pattern matching
            // with a regular expression.
            if (item.Comment != null)
            {
                // Our Starteam import put checkin date/time in Starteam as a commit comment.
                // Extract it and use it when we can; else use the commit date/time in TFS.
                Match match = new Regex(@"(\d+/\d+/\d+ \d+:\d+:\d+ ..):.*$").Match(item.Comment);
                if (match.Success)
                {
                    return DateTimeToUnix(match.Groups[1].Value);
                }
            }

            return DateTimeToUnix(item.CreationDate);
        }
示例#21
0
        internal static Changeset FromXml(Repository repository, XmlReader reader)
        {
            string elementName = reader.Name;

            Changeset changeset = new Changeset();

            changeset.versionControlServer = repository.VersionControlServer;

            changeset.committer   = reader.GetAttribute("cmtr");
            changeset.changesetId = Convert.ToInt32(reader.GetAttribute("cset"));
            string date = reader.GetAttribute("date");

            changeset.creationDate = DateTime.ParseExact(date, DateTimeFormats, null, DateTimeStyles.None);
            changeset.owner        = reader.GetAttribute("owner");

            List <Change> changes = new List <Change>();

            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.EndElement && reader.Name == elementName)
                {
                    break;
                }

                if (reader.NodeType == XmlNodeType.Element)
                {
                    switch (reader.Name)
                    {
                    case "Change":
                        changes.Add(Change.FromXml(repository, reader));
                        break;

                    case "Comment":
                        changeset.comment = reader.ReadString();
                        break;
                    }
                }
            }

            changeset.changes = changes.ToArray();
            return(changeset);
        }
        public string GetFileContent(Changeset commit, string path)
        {
            Changeset changeset = _versionControl.GetChangeset(commit.ChangesetId, true, true);
            Change change = changeset.Changes.FirstOrDefault(ch => ch.Item.ServerItem.Equals(path));

            if (change == null)
                return string.Empty;

            if (change.Item.ItemType != ItemType.File)
                return "This is a folder.";

            string content;
            Stream stream = change.Item.DownloadFile();

            using (StreamReader reader = new StreamReader(stream))
            {
                content = reader.ReadToEnd();
            }

            return content;
        }
示例#23
0
 protected override bool HasWorkItems(Changeset changeset)
 {
     return Retry.Do(() => changeset.AssociatedWorkItems.Length > 0);
 }
示例#24
0
 //public async Task<ExtendedMerge> TrackChangesetInAsync(Changeset changeset, string projectPath, string branch)
 //{
 //    var result = await TrackChangesetInAsync(changeset.ChangesetId, projectPath, new[] { branch });
 //    return result.FirstOrDefault();
 //}
 //public async Task<ExtendedMerge[]> TrackChangesetInAsync(Changeset changeset, string projectPath, IEnumerable<string> branches)
 //{
 //    var result = await TrackChangesetInAsync(changeset.ChangesetId, projectPath, branches);
 //    return result;
 //}
 ///// <summary>
 ///// Track a changeset merged into a possible list of branches.
 ///// </summary>
 ///// <param name="changesetId">The changeset ID to track</param>
 ///// <param name="projectPath">The source path of the changeset eg $/project/dev</param>
 ///// <param name="branches">A list of paths to check if the changeset has been merged into</param>
 ///// <returns>An array of Extended Merge</returns>
 //public async Task<ExtendedMerge[]> TrackChangesetInAsync(int changesetId, string projectPath, IEnumerable<string> branches)
 //{
 //    var t = await Task.Run(() =>
 //    {
 //        var result = TrackChangesetIn(changesetId, projectPath, branches);
 //        return result;
 //    });
 //    return t;
 //}
 public ExtendedMerge TrackChangesetIn(Changeset changeset, string projectPath, string branch)
 {
     var result = TrackChangesetIn(changeset.ChangesetId, projectPath, new[] { branch });
     return result.FirstOrDefault();
 }
示例#25
0
 private ITfsChangeset BuildTfsChangeset(Changeset changeset, GitTfsRemote remote)
 {
     return new TfsChangeset(this, _bridge.Wrap(changeset))
     {
         Summary = new TfsChangesetInfo { ChangesetId = changeset.ChangesetId, Remote = remote }
     };
 }
示例#26
0
 public Changeset(tfs.Changeset changeset)
 {
     _changeset = changeset;
     Version    = new Version(changeset.ChangesetId);
 }
        /// <summary>
        ///   Convert the passed changeset to an array of modifcations.
        /// </summary>
        private Modification[] toModifcations(Changeset changeset)
        {
            List<Modification> modifications = new List<Modification>();

            string userName = changeset.Committer;
            string comment = changeset.Comment;
            int changeNumber = changeset.ChangesetId;
            // In VSTS, the version of the file is the same as the changeset number it was checked in with.
            string version = Convert.ToString(changeNumber);

            DateTime modifedTime = this.TFS.TimeZone.ToLocalTime(changeset.CreationDate);

            foreach (Change change in changeset.Changes)
            {
                Modification modification = new Modification();
                modification.UserName = userName;
                modification.Comment = comment;
                modification.ChangeNumber = changeNumber;
                modification.ModifiedTime = modifedTime;
                modification.Version = version;
                modification.Type = PendingChange.GetLocalizedStringForChangeType(change.ChangeType);

                // Populate fields from change item
                Item item = change.Item;
                if (item.ItemType == ItemType.File)
                {
                    // split into foldername and filename
                    int lastSlash = item.ServerItem.LastIndexOf('/');
                    modification.FileName = item.ServerItem.Substring(lastSlash + 1);
                    // patch to the following line submitted by Ralf Kretzschmar.
                    modification.FolderName = item.ServerItem.Substring(0, lastSlash);
                }
                else
                {
                    // TODO - what should filename be if dir??  Empty string or null?
                    modification.FileName = string.Empty;
                    modification.FolderName = item.ServerItem;
                }
                Log.Debug(modification.ToString());
                modifications.Add(modification);
            }

            return modifications.ToArray();
        }
示例#28
0
        public GetStatus Get(GetRequest[] requests, GetOptions options,
                             GetFilterCallback filterCallback, object userData)
        {
            bool force = ((GetOptions.Overwrite & options) == GetOptions.Overwrite);
            bool noGet = false;             // not implemented below: ((GetOptions.Preview & options) == GetOptions.Preview);

            SortedList <int, DateTime> changesetDates = new SortedList <int, DateTime>();

            GetOperation[] getOperations = Repository.Get(Name, OwnerName, requests, force, noGet);
            if (null != filterCallback)
            {
                filterCallback(this, getOperations, userData);
            }

            UpdateLocalVersionQueue updates = new UpdateLocalVersionQueue(this);

            foreach (GetOperation getOperation in getOperations)
            {
                string           uPath = null;
                GettingEventArgs args  = new GettingEventArgs(this, getOperation);

                // Console.WriteLine(getOperation.ToString());

                if (getOperation.DeletionId != 0)
                {
                    if ((getOperation.ItemType == ItemType.Folder) &&
                        (Directory.Exists(getOperation.SourceLocalItem)))
                    {
                        UnsetDirectoryAttributes(getOperation.SourceLocalItem);
                        Directory.Delete(getOperation.SourceLocalItem, true);
                    }
                    else if ((getOperation.ItemType == ItemType.File) &&
                             (File.Exists(getOperation.SourceLocalItem)))
                    {
                        UnsetFileAttributes(getOperation.SourceLocalItem);
                        File.Delete(getOperation.SourceLocalItem);
                    }
                }
                else if ((!String.IsNullOrEmpty(getOperation.TargetLocalItem)) &&
                         (!String.IsNullOrEmpty(getOperation.SourceLocalItem)) &&
                         (getOperation.SourceLocalItem != getOperation.TargetLocalItem))
                {
                    uPath = getOperation.TargetLocalItem;
                    try
                    {
                        File.Move(getOperation.SourceLocalItem, getOperation.TargetLocalItem);
                    }
                    catch (IOException)
                    {
                        args.Status = OperationStatus.TargetIsDirectory;
                    }
                }
                else if (getOperation.ChangeType == ChangeType.None &&
                         getOperation.VersionServer != 0)
                {
                    uPath = getOperation.TargetLocalItem;
                    string directory = uPath;

                    if (getOperation.ItemType == ItemType.File)
                    {
                        directory = Path.GetDirectoryName(uPath);
                    }

                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    if (getOperation.ItemType == ItemType.File)
                    {
                        DownloadFile.WriteTo(uPath, Repository, getOperation.ArtifactUri);

                        // ChangesetMtimes functionality : none standard!
                        if (mTimeSetting)
                        {
                            int      cid = getOperation.VersionServer;
                            DateTime modDate;

                            if (!changesetDates.TryGetValue(cid, out modDate))
                            {
                                Changeset changeset = VersionControlServer.GetChangeset(cid);
                                modDate = changeset.CreationDate;
                                changesetDates.Add(cid, modDate);
                            }

                            File.SetLastWriteTime(uPath, modDate);
                        }

                        // do this after setting the last write time!
                        SetFileAttributes(uPath);
                    }
                }

                versionControlServer.OnDownloading(args);
                updates.QueueUpdate(getOperation.ItemId, uPath, getOperation.VersionServer);
            }

            updates.Flush();
            return(new GetStatus(getOperations.Length));
        }
示例#29
0
        void BuildChangesetZip(ZipOutputStream zip, Changeset changeset)
        {
            Console.WriteLine("Processing changeset " + changeset.ChangesetId);
            foreach (var change in changeset.Changes)
            {
                var item = change.Item;
                Log.DebugFormat("Processing change for {0}", item.ServerItem);
                if (!VerifyChange(item, change))
                {
                    Log.DebugFormat("VerifyChange returned false, skipping {0}", item.ServerItem);
                    continue;
                }

                var localPath = _workspace.GetLocalItemForServerItem(item.ServerItem);

                string entryName = null;
                if (localPath.Contains(_root))
                    entryName = localPath.Substring(_root.Length).TrimStart('\\');
                if (entryName == null || item.ItemType != ItemType.File)
                {
                    Log.DebugFormat("Skipping {0}", item.ServerItem);
                    continue;
                }
                if (entryName.EndsWith(".refresh"))
                    entryName = entryName.Substring(0, entryName.Length - ".refresh".Length);

                Console.WriteLine("Packing " + entryName);

                Stream fileStream = GetStreamFromItem(item);
                var entry = new ZipEntry(entryName);
                zip.PutNextEntry(entry);
                var buffer = new byte[4096];
                StreamUtils.Copy(fileStream, zip, buffer);

                _addedItems.Add(item.ServerItem);

                zip.CloseEntry();
            }
        }
示例#30
0
        // based on: https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples
        private void BuildBackupZip(ZipOutputStream zip, Changeset cs, string backupDir)
        {
            Console.WriteLine("Processing changeset " + cs.ChangesetId);
            foreach (var change in cs.Changes)
            {
                Item item = change.Item;
                if (!VerifyBackup(item, change))
                    continue;

                var localPath = _workspace.GetLocalItemForServerItem(item.ServerItem);

                string entryName = null;
                if (localPath.Contains(_root))
                    entryName = localPath.Substring(_root.Length).TrimStart('\\');

                // null if there is no mapping for the server file in this local path specified
                if (entryName == null)
                    continue;

                // support for .refresh files, grab the actual dll
                if (entryName.EndsWith(".refresh"))
                    entryName = entryName.Substring(0, entryName.Length - ".refresh".Length);

                var filename = backupDir + "\\" + entryName;

                if (!File.Exists(filename))
                    // we may arrive here if the ChangeType == Merge and its actually an Add operation.
                    // damn you TFS.
                    continue;

                Console.WriteLine("Packing " + filename);

                var entry = new ZipEntry(entryName);
                zip.PutNextEntry(entry);
                var buffer = new byte[4096];
                using (FileStream sr = File.OpenRead(filename))
                    StreamUtils.Copy(sr, zip, buffer);

                _backedupItems.Add(item.ServerItem);

                zip.CloseEntry();
            }
        }
示例#31
0
            public bool ApplyDiff(Changeset changeset, Dictionary<int, int> diff)
            {
                bool done = true;

                for (int i = 0; i < revisions.Length; i++)
                {
                    if (revisions[i] == UNKNOWN)
                    {
                        int line = mappings[i];
                        if (!diff.ContainsKey(line))
                        {
                            Associate(i, changeset);
                        }
                        else
                        {
                            mappings[i] = diff[line];
                            done = false;
                        }
                    }
                }

                return done;
            }
示例#32
0
        internal static Changeset FromXml(Repository repository, XmlReader reader)
        {
            string elementName = reader.Name;

            Changeset changeset = new Changeset();
            changeset.versionControlServer = repository.VersionControlServer;

            changeset.committer = reader.GetAttribute("cmtr");
            changeset.changesetId = Convert.ToInt32(reader.GetAttribute("cset"));
            string date = reader.GetAttribute("date");
            changeset.creationDate = DateTime.ParseExact(date, DateTimeFormats, null, DateTimeStyles.None);
            changeset.owner = reader.GetAttribute("owner");

             			List<Change> changes = new List<Change>();

            while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.EndElement && reader.Name == elementName)
                        break;

                    if (reader.NodeType == XmlNodeType.Element)
                        {
                            switch (reader.Name)
                                {
                                case "Change":
                                    changes.Add(Change.FromXml(repository, reader));
                                    break;
                                case "Comment":
                                    changeset.comment = reader.ReadString();
                                    break;
                                }
                        }
                }

            changeset.changes = changes.ToArray();
            return changeset;
        }
示例#33
0
        private void UndeleteFolder(Changeset changeset, Change change)
        {
            string itemPath = GetItemPath(change.Item);
            Directory.CreateDirectory(itemPath);

            if (this.FolderUndeleted != null)
                this.FolderUndeleted(changeset.ChangesetId, itemPath, changeset.Committer, changeset.Comment, changeset.CreationDate);
        }
示例#34
0
 public void Apply(Changeset changeset)
 {
     for (int i = 0; i < revisions.Length; i++)
     {
         if (revisions[i] == UNKNOWN)
         {
             Associate(i, changeset);
         }
     }
 }
示例#35
0
        private void UndeleteFile(Changeset changeset, Change change)
        {
            string itemPath = GetItemPath(change.Item);
            DownloadItemFile(change, itemPath);

            if (this.FileUndeleted != null)
                this.FileUndeleted(changeset.ChangesetId, itemPath, changeset.Committer, changeset.Comment, changeset.CreationDate);
        }
示例#36
0
 private void Associate(int line, Changeset changeset)
 {
     int changesetId = changeset != null ? changeset.ChangesetId : LOCAL;
     revisions[line] = changesetId;
     if (!changesets.ContainsKey(changesetId))
     {
         changesets.Add(changesetId, changeset);
     }
 }
示例#37
0
        public ChangesetMerge[] QueryMerges(string workspaceName, string workspaceOwner,
                                            ItemSpec source, VersionSpec versionSource,
                                            ItemSpec target, VersionSpec versionTarget,
                                            VersionSpec versionFrom, VersionSpec versionTo,
                                            int maxChangesets)
        {
            Message msg = new Message(GetWebRequest(new Uri(Url)), "QueryMerges");

            if (!String.IsNullOrEmpty(workspaceName))
            {
                msg.Body.WriteElementString("workspaceName", workspaceName);
            }
            if (!String.IsNullOrEmpty(workspaceOwner))
            {
                msg.Body.WriteElementString("workspaceOwner", workspaceOwner);
            }

            if (source != null)
            {
                source.ToXml(msg.Body, "source");
            }
            if (versionSource != null)
            {
                versionSource.ToXml(msg.Body, "versionSource");
            }

            target.ToXml(msg.Body, "target");
            versionTarget.ToXml(msg.Body, "versionTarget");

            if (versionFrom != null)
            {
                versionFrom.ToXml(msg.Body, "versionFrom");
            }
            if (versionTo != null)
            {
                versionTo.ToXml(msg.Body, "versionTo");
            }

            msg.Body.WriteElementString("maxChangesets", Convert.ToString(maxChangesets));

            List <ChangesetMerge>       merges     = new List <ChangesetMerge>();
            Dictionary <int, Changeset> changesets = new Dictionary <int, Changeset>();

            using (HttpWebResponse response = Invoke(msg))
            {
                XmlReader results = msg.ResponseReader(response);

                while (results.Read())
                {
                    if (results.NodeType != XmlNodeType.Element)
                    {
                        continue;
                    }

                    if (results.Name == "ChangesetMerge")
                    {
                        merges.Add(ChangesetMerge.FromXml(this, results));
                    }
                    else if (results.Name == "Changeset")
                    {
                        Changeset changeset = Changeset.FromXml(this, results);
                        changesets.Add(changeset.ChangesetId, changeset);
                    }
                }
            }

            foreach (ChangesetMerge merge in merges)
            {
                Changeset changeset;
                if (changesets.TryGetValue(merge.TargetVersion, out changeset))
                {
                    merge.TargetChangeset = changeset;
                }
            }

            return(merges.ToArray());
        }