public WorkItem FindReflectedWorkItemByTitle(string title) { TfsQueryContext query = new TfsQueryContext(this); query.Query = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject]=@TeamProject AND [System.Title] = @TitleToFind"; query.AddParameter("TitleToFind", title); query.AddParameter("TeamProject", this.targetTfs.Name); return(FindWorkItemByQuery(query)); }
public WorkItem FindReflectedWorkItemByMigrationRef(string refId) { TfsQueryContext query = new TfsQueryContext(this); query.Query = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject]=@TeamProject AND [System.Description] Contains @KeyToFind"; query.AddParameter("KeyToFind", string.Format("##REF##{0}##", refId)); query.AddParameter("TeamProject", this.targetTfs.Name); return(FindWorkItemByQuery(query)); }
public WorkItem FindReflectedWorkItemByReflectedWorkItemId(string refId, string reflectedWotkItemIdField) { TfsQueryContext query = new TfsQueryContext(this); query.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject]=@TeamProject AND [{0}] = @idToFind", reflectedWotkItemIdField); query.AddParameter("idToFind", refId.ToString()); query.AddParameter("TeamProject", this.targetTfs.Name); return(FindWorkItemByQuery(query)); }
internal override void InternalExecute() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(targetStore); tfsqc.AddParameter("TeamProject", me.Target.Name); tfsqc.AddParameter("AreaPath", config.AreaIterationPath); tfsqc.Query = @"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject and [System.AreaPath] under @AreaPath"; WorkItemCollection workitems = tfsqc.Execute(); Trace.WriteLine(string.Format("Update {0} work items?", workitems.Count)); ////////////////////////////////////////////////// int current = workitems.Count; int count = 0; long elapsedms = 0; foreach (WorkItem workitem in workitems) { Stopwatch witstopwatch = new Stopwatch(); witstopwatch.Start(); Trace.WriteLine(string.Format("{0} - Updating: {1}-{2}", current, workitem.Id, workitem.Type.Name)); string areaPath = workitem.AreaPath; List <string> bits = new List <string>(areaPath.Split(char.Parse(@"\"))).Skip(4).ToList(); List <string> tags = workitem.Tags.Split(char.Parse(@";")).ToList(); List <string> newTags = tags.Union(bits).ToList(); string newTagList = string.Join(";", newTags.ToArray()); if (newTagList != workitem.Tags) { workitem.Open(); workitem.Tags = newTagList; workitem.Save(); } witstopwatch.Stop(); elapsedms = elapsedms + witstopwatch.ElapsedMilliseconds; current--; count++; TimeSpan average = new TimeSpan(0, 0, 0, 0, (int)(elapsedms / count)); TimeSpan remaining = new TimeSpan(0, 0, 0, 0, (int)(average.TotalMilliseconds * current)); Trace.WriteLine(string.Format("Average time of {0} per work item and {1} estimated to completion", string.Format(@"{0:s\:fff} seconds", average), string.Format(@"{0:%h} hours {0:%m} minutes {0:s\:fff} seconds", remaining))); } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
internal override void InternalExecute() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(targetStore); tfsqc.AddParameter("TeamProject", me.Target.Name); tfsqc.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] UNDER '{0}\_DeleteMe'", me.Target.Name); WorkItemCollection workitems = tfsqc.Execute(); Trace.WriteLine(string.Format("Update {0} work items?", workitems.Count)); ////////////////////////////////////////////////// int current = workitems.Count; //int count = 0; //long elapsedms = 0; var tobegone = (from WorkItem wi in workitems where wi.AreaPath.Contains("_DeleteMe") select wi.Id).ToList(); foreach (int begone in tobegone) { targetStore.Store.DestroyWorkItems(new List <int>() { begone }); Trace.WriteLine(string.Format("Deleted {0}", begone)); } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
internal override void InternalExecute() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.None); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Name); tfsqc.Query = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject ";// AND [System.Id] = 188708 "; WorkItemCollection sourceWIS = tfsqc.Execute(); Trace.WriteLine(string.Format("Migrate {0} work items?", sourceWIS.Count)); ////////////////////////////////////////////////// int current = sourceWIS.Count; foreach (WorkItem sourceWI in sourceWIS) { System.Threading.Thread.Sleep(10); } stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
internal override void InternalExecute() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.None); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Name); tfsqc.Query = string.Format(@"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY [System.ChangedDate] desc", _config.QueryBit); WorkItemCollection sourceWIS = tfsqc.Execute(); WebClient webClient = new WebClient(); webClient.Credentials = CredentialCache.DefaultNetworkCredentials; int current = sourceWIS.Count; foreach (WorkItem wi in sourceWIS) { Trace.Write(string.Format("Attachement Export: {0} of {1} - {2}", current, sourceWIS.Count, wi.Id)); foreach (Attachment wia in wi.Attachments) { string reflectedId = sourceStore.CreateReflectedWorkItemId(wi); string fname = string.Format("{0}#{1}", reflectedId.Replace("/", "-").Replace(":", "+"), wia.Name); Trace.Write("-"); Trace.Write(fname); string fpath = Path.Combine(exportPath, fname); if (!File.Exists(fpath)) { Trace.Write("...downloading"); try { webClient.DownloadFile(wia.Uri, fpath); Trace.Write("...done"); } catch (Exception ex) { Telemetry.Current.TrackException(ex); Trace.Write("...failed"); } } else { Trace.Write("...skipping"); } Trace.WriteLine("...done"); } current--; } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"EXPORT DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
internal override void InternalExecute() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(targetStore); tfsqc.AddParameter("TeamProject", me.Target.Name); tfsqc.Query = string.Format(@"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY [System.ChangedDate] desc", _config.QueryBit); WorkItemCollection workitems = tfsqc.Execute(); Trace.WriteLine(string.Format("Update {0} work items?", workitems.Count)); ////////////////////////////////////////////////// int current = workitems.Count; int count = 0; long elapsedms = 0; foreach (WorkItem workitem in workitems) { Stopwatch witstopwatch = new Stopwatch(); witstopwatch.Start(); workitem.Open(); Trace.WriteLine(string.Format("Processing work item {0} - Type:{1} - ChangedDate:{2} - CreatedDate:{3}", workitem.Id, workitem.Type.Name, workitem.ChangedDate.ToShortDateString(), workitem.CreatedDate.ToShortDateString())); _me.ApplyFieldMappings(workitem); if (workitem.IsDirty) { if (!_config.WhatIf) { try { workitem.Save(); } catch (Exception) { System.Threading.Thread.Sleep(5000); workitem.Save(); } } else { Trace.WriteLine("No save done: (What IF: enabled)"); } } else { Trace.WriteLine("No save done: (IsDirty: false)"); } witstopwatch.Stop(); elapsedms = elapsedms + witstopwatch.ElapsedMilliseconds; current--; count++; TimeSpan average = new TimeSpan(0, 0, 0, 0, (int)(elapsedms / count)); TimeSpan remaining = new TimeSpan(0, 0, 0, 0, (int)(average.TotalMilliseconds * current)); Trace.WriteLine(string.Format("Average time of {0} per work item and {1} estimated to completion", string.Format(@"{0:s\:fff} seconds", average), string.Format(@"{0:%h} hours {0:%m} minutes {0:s\:fff} seconds", remaining))); } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
internal override void InternalExecute() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Name); tfsqc.Query = string.Format(@"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY [System.ChangedDate] desc", _config.QueryBit); WorkItemCollection sourceWIS = tfsqc.Execute(); Trace.WriteLine(string.Format("Migrate {0} work items?", sourceWIS.Count), this.Name); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); Project destProject = targetStore.GetProject(); Trace.WriteLine(string.Format("Found target project as {0}", destProject.Name), this.Name); int current = sourceWIS.Count; int count = 0; long elapsedms = 0; foreach (WorkItem sourceWI in sourceWIS) { Stopwatch witstopwatch = new Stopwatch(); witstopwatch.Start(); WorkItem targetFound; targetFound = targetStore.FindReflectedWorkItem(sourceWI, me.ReflectedWorkItemIdFieldName, false); Trace.WriteLine(string.Format("{0} - Migrating: {1}-{2}", current, sourceWI.Id, sourceWI.Type.Name), this.Name); if (targetFound == null) { WorkItem newwit = null; // Deside on WIT if (me.WorkItemTypeDefinitions.ContainsKey(sourceWI.Type.Name)) { newwit = CreateAndPopulateWorkItem(_config, sourceWI, destProject, me.WorkItemTypeDefinitions[sourceWI.Type.Name].Map(sourceWI)); if (newwit.Fields.Contains(me.ReflectedWorkItemIdFieldName)) { newwit.Fields[me.ReflectedWorkItemIdFieldName].Value = sourceStore.CreateReflectedWorkItemId(sourceWI); } me.ApplyFieldMappings(sourceWI, newwit); ArrayList fails = newwit.Validate(); foreach (Field f in fails) { Trace.WriteLine(string.Format("{0} - Invalid: {1}-{2}-{3}", current, sourceWI.Id, sourceWI.Type.Name, f.ReferenceName), this.Name); } } else { Trace.WriteLine("...not supported", this.Name); } if (newwit != null) { try { if (_config.UpdateCreatedDate) { newwit.Fields["System.CreatedDate"].Value = sourceWI.Fields["System.CreatedDate"].Value; } if (_config.UpdateCreatedBy) { newwit.Fields["System.CreatedBy"].Value = sourceWI.Fields["System.CreatedBy"].Value; } newwit.Save(); newwit.Close(); Trace.WriteLine(string.Format("...Saved as {0}", newwit.Id), this.Name); if (sourceWI.Fields.Contains(me.ReflectedWorkItemIdFieldName) && _config.UpdateSoureReflectedId) { sourceWI.Fields[me.ReflectedWorkItemIdFieldName].Value = targetStore.CreateReflectedWorkItemId(newwit); } sourceWI.Save(); Trace.WriteLine(string.Format("...and Source Updated {0}", sourceWI.Id), this.Name); } catch (Exception ex) { Trace.WriteLine("...FAILED to Save", this.Name); foreach (Field f in newwit.Fields) { Trace.WriteLine(string.Format("{0} | {1}", f.ReferenceName, f.Value), this.Name); } Trace.WriteLine(ex.ToString(), this.Name); } } } else { Console.WriteLine("...Exists"); // sourceWI.Open(); // sourceWI.SyncToLatest(); // sourceWI.Fields["TfsMigrationTool.ReflectedWorkItemId"].Value = destWIFound[0].Id; //sourceWI.Save(); } sourceWI.Close(); witstopwatch.Stop(); elapsedms = elapsedms + witstopwatch.ElapsedMilliseconds; current--; count++; TimeSpan average = new TimeSpan(0, 0, 0, 0, (int)(elapsedms / count)); TimeSpan remaining = new TimeSpan(0, 0, 0, 0, (int)(average.TotalMilliseconds * current)); Trace.WriteLine(string.Format("Average time of {0} per work item and {1} estimated to completion", string.Format(@"{0:s\:fff} seconds", average), string.Format(@"{0:%h} hours {0:%m} minutes {0:s\:fff} seconds", remaining)), this.Name); Trace.Flush(); } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
internal override void InternalExecute() { try { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// var sourceGitRepoService = me.Source.Collection.GetService <GitRepositoryService>(); var sourceGitRepos = sourceGitRepoService.QueryRepositories(me.Source.Name); ////////////////////////////////////////////////// var targetGitRepoService = me.Target.Collection.GetService <GitRepositoryService>(); var targetGitRepos = targetGitRepoService.QueryRepositories(me.Target.Name); WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(targetStore); tfsqc.AddParameter("TeamProject", me.Target.Name); tfsqc.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.ExternalLinkCount] > 0 ", me.Target.Name); WorkItemCollection workitems = tfsqc.Execute(); Trace.WriteLine(string.Format("Update {0} work items?", workitems.Count)); ////////////////////////////////////////////////// int current = workitems.Count; int count = 0; long elapsedms = 0; int noteFound = 0; foreach (WorkItem workitem in workitems) { Stopwatch witstopwatch = new Stopwatch(); witstopwatch.Start(); workitem.Open(); List <ExternalLink> newEL = new List <ExternalLink>(); List <ExternalLink> removeEL = new List <ExternalLink>(); Trace.WriteLine(string.Format("WI: {0}?", workitem.Id)); foreach (Link l in workitem.Links) { if (l is ExternalLink && l.ArtifactLinkType.Name == "Fixed in Commit") { ExternalLink el = (ExternalLink)l; //vstfs:///Git/Commit/25f94570-e3e7-4b79-ad19-4b434787fd5a%2f50477259-3058-4dff-ba4c-e8c179ec5327%2f41dd2754058348d72a6417c0615c2543b9b55535 string guidbits = el.LinkedArtifactUri.Substring(el.LinkedArtifactUri.LastIndexOf('/') + 1); string[] bits = Regex.Split(guidbits, "%2f", RegexOptions.IgnoreCase); if (bits.Count() != 3) { throw new Exception("Regex to split bits in url is not working too great"); } string oldGitRepoId = bits[1]; string oldCommitId = bits[2]; var oldGitRepo = (from g in sourceGitRepos where g.Id.ToString() == oldGitRepoId select g).SingleOrDefault(); if (oldGitRepo != null && oldGitRepo.ProjectReference.Name != me.Target.Name) { var newGitRepo = (from g in targetGitRepos where g.Name == oldGitRepo.Name && g.ProjectReference.Name != oldGitRepo.ProjectReference.Name select g).SingleOrDefault(); if (newGitRepo != null) { /// we have FOUND Trace.WriteLine(string.Format("Found {0} to {1}?", oldGitRepo.RemoteUrl, newGitRepo.RemoteUrl)); string link = string.Format("vstfs:///git/commit/{0}%2f{1}%2f{2}", newGitRepo.ProjectReference.Id.ToString(), newGitRepo.Id.ToString(), oldCommitId); var elinks = from Link lq in workitem.Links where lq.ArtifactLinkType.Name == "Fixed in Commit" select(ExternalLink) lq; var found = (from Link lq in elinks where (((ExternalLink)lq).LinkedArtifactUri.ToLower() == link.ToLower()) select lq).SingleOrDefault(); if (found == null) { newEL.Add(new ExternalLink(targetStore.Store.RegisteredLinkTypes[ArtifactLinkIds.Commit], link)); } removeEL.Add(el); } else { Trace.WriteLine(string.Format("FAIL {0} to ???", oldGitRepo.RemoteUrl)); } } else { Trace.WriteLine(string.Format("FAIL {0} to ???", oldGitRepoId)); noteFound++; } } } /// add and remove foreach (ExternalLink eln in newEL) { try { Trace.WriteLine(string.Format("Addming ", eln.LinkedArtifactUri)); workitem.Links.Add(eln); } catch (Exception) { // eat exception as somtimes TFS thinks this is an attachemnt } } foreach (ExternalLink elr in removeEL) { if (workitem.Links.Contains(elr)) { try { Trace.WriteLine(string.Format("Removing ", elr.LinkedArtifactUri)); workitem.Links.Remove(elr); } catch (Exception) { // eat exception as somtimes TFS thinks this is an attachemnt } } } if (workitem.IsDirty) { Trace.WriteLine(string.Format("Saving ")); workitem.Save(); } witstopwatch.Stop(); elapsedms = elapsedms + witstopwatch.ElapsedMilliseconds; current--; count++; TimeSpan average = new TimeSpan(0, 0, 0, 0, (int)(elapsedms / count)); TimeSpan remaining = new TimeSpan(0, 0, 0, 0, (int)(average.TotalMilliseconds * current)); Trace.WriteLine(string.Format("Average time of {0} per work item and {1} estimated to completion", string.Format(@"{0:s\:fff} seconds", average), string.Format(@"{0:%h} hours {0:%m} minutes {0:s\:fff} seconds", remaining))); } Trace.WriteLine(string.Format("Did not find old repo for {0} links?", noteFound)); ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); } catch (Exception ex) { throw ex; } }
internal override void InternalExecute() { WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Name); tfsqc.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY [System.ChangedDate] desc ", config.QueryBit); // AND [Microsoft.VSTS.Common.ClosedDate] = '' WorkItemCollection sourceWIS = tfsqc.Execute(); ////////////////////////////////////////////////// Trace.WriteLine(string.Format("Migrate {0} work items links?", sourceWIS.Count), "LinkMigrationContext"); int current = sourceWIS.Count; ////////////////////////////////////////////////// WorkItemStoreContext targetWitsc = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); Project targetProj = targetWitsc.GetProject(); ////////////////////////////////////////////////// foreach (WorkItem wiSourceL in sourceWIS) { Trace.WriteLine(string.Format("Migrating Links for wiSourceL={0}", wiSourceL.Id), "LinkMigrationContext"); WorkItem wiTargetL = targetWitsc.FindReflectedWorkItem(wiSourceL, me.ReflectedWorkItemIdFieldName, true); if (wiTargetL == null) { //wiSourceL was not migrated, or the migrated work item has been deleted. Trace.WriteLine(string.Format("[SKIP] Unable to migrate links where wiSourceL={0}, wiTargetL=NotFound", wiSourceL.Id), "LinkMigrationContext"); continue; } Trace.WriteLine(string.Format("Found Target Left wiSourceL={0}, wiTargetL=NotFound", wiSourceL.Id), "LinkMigrationContext"); if (wiTargetL.Links.Count == wiSourceL.Links.Count) { Trace.WriteLine(string.Format("[SKIP] SOurce and Target have same number of links {0} - {1}", wiSourceL.Id, wiSourceL.Type.ToString()), "LinkMigrationContext"); } else { try { Trace.Indent(); foreach (Link item in wiSourceL.Links) { Trace.WriteLine(string.Format("Migrating link for {0} of type {1}", wiSourceL.Id, item.GetType().Name), "LinkMigrationContext"); if (IsHyperlink(item)) { CreateHyperlink((Hyperlink)item, wiTargetL); } else if (IsRelatedLink(item)) { RelatedLink rl = (RelatedLink)item; CreateRelatedLink(wiSourceL, rl, wiTargetL, sourceStore, targetWitsc); } else if (IsExternalLink(item)) { ExternalLink rl = (ExternalLink)item; CreateExternalLink((ExternalLink)item, wiTargetL); } else { UnknownLinkTypeException ex = new UnknownLinkTypeException(string.Format(" [UnknownLinkType] Unable to {0}", item.GetType().Name)); Telemetry.Current.TrackException(ex); Trace.WriteLine(ex.ToString(), "LinkMigrationContext"); throw ex; } } } catch (WorkItemLinkValidationException ex) { wiSourceL.Reset(); wiTargetL.Reset(); Telemetry.Current.TrackException(ex); Trace.WriteLine(string.Format(" [WorkItemLinkValidationException] Adding link for wiSourceL={0}", wiSourceL.Id), "LinkMigrationContext"); Trace.WriteLine(ex.ToString(), "LinkMigrationContext"); } catch (Exception ex) { Telemetry.Current.TrackException(ex); Trace.WriteLine(string.Format(" [CREATE-FAIL] Adding Link for wiSourceL={0}", wiSourceL.Id), "LinkMigrationContext"); Trace.WriteLine(ex.ToString(), "LinkMigrationContext"); } } current--; } }
//public WorkItemPostProcessingContext(MigrationEngine me, WorkItemPostProcessingConfig config, IList<string> wiTypes) : this(me, config) //{ // _workItemTypes = wiTypes; //} //public WorkItemPostProcessingContext(MigrationEngine me, WorkItemPostProcessingConfig config, IList<int> wiIDs) : this(me, config) //{ // _workItemIDs = wiIDs; //} //public WorkItemPostProcessingContext(MigrationEngine me, WorkItemPostProcessingConfig config, string queryBit) : this (me, config) //{ // _queryBit = queryBit; //} internal override void InternalExecute() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ////////////////////////////////////////////////// WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.None); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Name); //Builds the constraint part of the query string constraints = BuildQueryBitConstraints(); tfsqc.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY [System.Id] ", constraints); WorkItemCollection sourceWIS = tfsqc.Execute(); Trace.WriteLine(string.Format("Migrate {0} work items?", sourceWIS.Count)); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); Project destProject = targetStore.GetProject(); Trace.WriteLine(string.Format("Found target project as {0}", destProject.Name)); int current = sourceWIS.Count; int count = 0; long elapsedms = 0; foreach (WorkItem sourceWI in sourceWIS) { Stopwatch witstopwatch = new Stopwatch(); witstopwatch.Start(); WorkItem targetFound; targetFound = targetStore.FindReflectedWorkItem(sourceWI, me.ReflectedWorkItemIdFieldName, false); Trace.WriteLine(string.Format("{0} - Updating: {1}-{2}", current, sourceWI.Id, sourceWI.Type.Name)); if (targetFound == null) { Trace.WriteLine(string.Format("{0} - WARNING: does not exist {1}-{2}", current, sourceWI.Id, sourceWI.Type.Name)); } else { Console.WriteLine("...Exists"); targetFound.Open(); me.ApplyFieldMappings(sourceWI, targetFound); if (targetFound.IsDirty) { try { targetFound.Save(); Trace.WriteLine(string.Format(" Updated")); } catch (ValidationException ve) { Trace.WriteLine(string.Format(" [FAILED] {0}", ve.ToString())); } } else { Trace.WriteLine(string.Format(" No changes")); } sourceWI.Close(); } witstopwatch.Stop(); elapsedms = elapsedms + witstopwatch.ElapsedMilliseconds; current--; count++; TimeSpan average = new TimeSpan(0, 0, 0, 0, (int)(elapsedms / count)); TimeSpan remaining = new TimeSpan(0, 0, 0, 0, (int)(average.TotalMilliseconds * current)); Trace.WriteLine(string.Format("Average time of {0} per work item and {1} estimated to completion", string.Format(@"{0:s\:fff} seconds", average), string.Format(@"{0:%h} hours {0:%m} minutes {0:s\:fff} seconds", remaining))); } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }