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 = Stopwatch.StartNew(); ////////////////////////////////////////////////// WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.None); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Config.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(); int current = sourceWIS.Count; var workItemServer = me.Source.Collection.GetService <WorkItemServer>(); var invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (WorkItem wi in sourceWIS) { WorkItemAttachmentExport(workItemServer, wi); current++; } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"EXPORT DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
public WorkItem FindReflectedWorkItemByReflectedWorkItemId(int refId, bool cache) { var sourceIdKey = ~refId; if (foundWis.TryGetValue(sourceIdKey, out var workItem)) { return(workItem); } IEnumerable <WorkItem> QueryWorkItems() { TfsQueryContext query = new TfsQueryContext(this); query.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject]=@TeamProject AND [{0}] Contains '@idToFind'", teamProjectContext.Config.ReflectedWorkItemIDFieldName); query.AddParameter("idToFind", refId.ToString()); query.AddParameter("TeamProject", this.teamProjectContext.Config.Project); foreach (WorkItem wi in query.Execute()) { yield return(wi); } } var foundWorkItem = QueryWorkItems().FirstOrDefault(wi => wi.Fields[teamProjectContext.Config.ReflectedWorkItemIDFieldName].Value.ToString().EndsWith("/" + refId)); if (cache && foundWorkItem != null) { foundWis[sourceIdKey] = foundWorkItem; } return(foundWorkItem); }
internal override void InternalExecute() { Stopwatch stopwatch = Stopwatch.StartNew(); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(targetStore); tfsqc.AddParameter("TeamProject", me.Target.Config.Project); tfsqc.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] UNDER '{0}\_DeleteMe'", me.Target.Config.Project); 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 = 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(); int current = sourceWIS.Count; var workItemServer = me.Source.Collection.GetService <WorkItemServer>(); var invalidFileNameChars = Path.GetInvalidFileNameChars(); 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 fname = string.Format("{0}#{1}", wi.Id, wia.Name); fname = GetSafeFilename(fname); Trace.Write("-"); Trace.Write(fname); string fpath = Path.Combine(exportPath, fname); if (!File.Exists(fpath)) { Trace.Write("...downloading"); try { var fileLocation = workItemServer.DownloadFile(wia.Id); File.Copy(fileLocation, fpath, true); Trace.Write("...done"); } catch (Exception ex) { Telemetry.Current.TrackException(ex); Trace.Write($"\r\nException downloading attachements {ex.Message}"); } } 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 = Stopwatch.StartNew(); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(targetStore); TfsTeamService teamService = me.Target.Collection.GetService <TfsTeamService>(); QueryHierarchy qh = targetStore.Store.Projects[me.Target.Config.Project].QueryHierarchy; List <TeamFoundationTeam> teamList = teamService.QueryTeams(me.Target.Config.Project).ToList(); Trace.WriteLine(string.Format("Found {0} teams?", teamList.Count)); ////////////////////////////////////////////////// int current = teamList.Count; int count = 0; long elapsedms = 0; foreach (TeamFoundationTeam team in teamList) { Stopwatch witstopwatch = Stopwatch.StartNew(); Trace.Write(string.Format("Processing team {0}", team.Name)); Regex r = new Regex(@"^Project - ([a-zA-Z ]*)"); string path; if (r.IsMatch(team.Name)) { Trace.Write(string.Format(" is a Project")); path = string.Format(@"Projects\{0}", r.Match(team.Name).Groups[1].Value.Replace(" ", "-")); } else { Trace.Write(string.Format(" is a Team")); path = string.Format(@"Teams\{0}", team.Name.Replace(" ", "-")); } Trace.Write(string.Format(" and new path is {0}", path)); //me.AddFieldMap("*", new RegexFieldMap("KM.Simulation.Team", "System.AreaPath", @"^Project - ([a-zA-Z ]*)", @"Nemo\Projects\$1")); string[] bits = path.Split(char.Parse(@"\")); CreateFolderHyerarchy(bits, qh["Shared Queries"]); //_me.ApplyFieldMappings(workitem); qh.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(""); //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); }
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 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); }
public WorkItem FindReflectedWorkItemByMigrationRef(string refId) { TfsQueryContext query = new TfsQueryContext(this); StringBuilder queryBuilder = FindReflectedWorkItemQueryBase(query); queryBuilder.Append(" [System.Description] Contains @KeyToFind"); query.AddParameter("KeyToFind", string.Format("##REF##{0}##", refId)); query.Query = queryBuilder.ToString(); return(FindWorkItemByQuery(query)); }
public WorkItem FindReflectedWorkItemByReflectedWorkItemId(string refId) { TfsQueryContext query = new TfsQueryContext(this); StringBuilder queryBuilder = FindReflectedWorkItemQueryBase(query); queryBuilder.AppendFormat("[{0}] = @idToFind", teamProjectContext.Config.ReflectedWorkItemIDFieldName); query.AddParameter("idToFind", refId.ToString()); query.Query = queryBuilder.ToString(); return(FindWorkItemByQuery(query)); }
public WorkItem FindWorkItemByQuery(TfsQueryContext query) { WorkItemCollection newFound; newFound = query.Execute(); if (newFound.Count == 0) { return null; } return newFound[0]; }
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 = $@"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {_config.QueryBit} ORDER BY [System.ChangedDate] desc"; WorkItemCollection targetWIS = tfsqc.Execute(); Trace.WriteLine($"Found {targetWIS.Count} work items...", Name); current = targetWIS.Count; string urlForMatch = me.Source.Collection.Uri.ToString(); if (_config.FromAnyCollection) { var url = new Uri(me.Source.Collection.Uri.ToString()); urlForMatch = url.GetLeftPart(UriPartial.Authority); } Trace.WriteLine($"Searching for urls: {urlForMatch} and {GetUrlWithOppositeSchema(urlForMatch)} {_config.SourceServerAliases?.Select(alias => "and " + alias)}"); foreach (WorkItem targetWi in targetWIS) { Trace.WriteLine($"{current} - Fixing: {targetWi.Id}-{targetWi.Type.Name}", Name); // Decide on WIT if (me.WorkItemTypeDefinitions.ContainsKey(targetWi.Type.Name)) { FixHtmlAttachmentLinks(targetWi, urlForMatch, me.Target.Collection.Uri.ToString()); } else { Trace.WriteLine( $"...the WITD named {targetWi.Type.Name} is not in the list provided in the configuration.json under WorkItemTypeDefinitions. Add it to the list to enable migration of this work item type.", Name); skipped++; } current--; count++; Trace.Flush(); } stopwatch.Stop(); Trace.WriteLine($@"DONE in {stopwatch.Elapsed:%h} hours {stopwatch.Elapsed:%m} minutes {stopwatch.Elapsed:s\:fff} seconds - {targetWIS.Count} Items, {updated} Updated, {skipped} Skipped, {failures} Failures, {candidates} Possible Candidates, {notfound} Not Found", this.Name); }
internal override void InternalExecute() { var stopwatch = Stopwatch.StartNew(); ////////////////////////////////////////////////// var sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.BypassRules); var tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Config.Project); tfsqc.Query = string.Format( @"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY {1}", _config.QueryBit, _config.OrderBit); var sourceQueryResult = tfsqc.Execute(); var sourceWorkItems = (from WorkItem swi in sourceQueryResult select swi).ToList(); Trace.WriteLine($"Replay all revisions of {sourceWorkItems.Count} work items?", Name); ////////////////////////////////////////////////// var targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); var destProject = targetStore.GetProject(); Trace.WriteLine($"Found target project as {destProject.Name}", Name); //////////////////////////////////////////////////////////FilterCompletedByQuery if (_config.FilterWorkItemsThatAlreadyExistInTarget) { sourceWorkItems = FilterWorkItemsThatAlreadyExistInTarget(sourceWorkItems, targetStore); } ////////////////////////////////////////////////// _current = 1; _count = sourceWorkItems.Count; _elapsedms = 0; _totalWorkItem = sourceWorkItems.Count; //Validation: make sure that the ReflectedWorkItemId field name specified in the config exists in the target process, preferably on each work item type. ConfigValidation(); foreach (WorkItem sourceWorkItem in sourceWorkItems) { ProcessWorkItem(sourceStore, targetStore, destProject, sourceWorkItem, _config.WorkItemCreateRetryLimit); if (_config.PauseAfterEachWorkItem) { Console.WriteLine("Do you want to continue? (y/n)"); if (Console.ReadKey().Key != ConsoleKey.Y) { Trace.WriteLine("USER ABORTED", "[Warning]"); break; } } } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
internal override void InternalExecute() { Stopwatch stopwatch = Stopwatch.StartNew(); ////////////////////////////////////////////////// WorkItemStoreContext targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); var targetQuery = new TfsQueryContext(targetStore); targetQuery.AddParameter("TeamProject", me.Target.Config.Project); targetQuery.Query = string.Format( @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY {1}", _config.QueryBit, _config.OrderBit ); WorkItemCollection workitems = targetQuery.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 = Stopwatch.StartNew(); workitem.Open(); _RepoOMatic.FixExternalLinks(workitem, targetStore, null); if (workitem.IsDirty) { Trace.WriteLine($"Saving {workitem.Id}"); 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); }
private StringBuilder FindReflectedWorkItemQueryBase(TfsQueryContext query) { StringBuilder s = new StringBuilder(); s.Append("SELECT [System.Id] FROM WorkItems"); s.Append(" WHERE "); if (!teamProjectContext.Config.AllowCrossProjectLinking) { s.Append("[System.TeamProject]=@TeamProject AND "); query.AddParameter("TeamProject", this.teamProjectContext.Config.Project); } return(s); }
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.Id] ", _config.QueryBit); WorkItemCollection targetWIS = tfsqc.Execute(); Trace.WriteLine(string.Format("Found {0} work items...", targetWIS.Count), Name); current = targetWIS.Count; string urlForMatch = me.Source.Collection.Uri.ToString(); if (_config.FromAnyCollection) { var url = new Uri(me.Source.Collection.Uri.ToString()); urlForMatch = url.GetLeftPart(UriPartial.Authority); } Trace.WriteLine(String.Format("Searching for urls: {0} and {1}", urlForMatch, GetUrlWithOppositeSchema(urlForMatch))); foreach (WorkItem targetWi in targetWIS) { Trace.WriteLine(string.Format("{0} - Fixing: {1}-{2}", current, targetWi.Id, targetWi.Type.Name), Name); // Deside on WIT if (me.WorkItemTypeDefinitions.ContainsKey(targetWi.Type.Name)) { FixHtmlAttachmentLinks(targetWi, urlForMatch, me.Target.Collection.Uri.ToString()); } else { Trace.WriteLine("...not supported", Name); skipped++; } current--; count++; Trace.Flush(); } ////////////////////////////////////////////////// stopwatch.Stop(); Trace.WriteLine(string.Format(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds - {1} Items, {2} Updated, {3} Skipped, {4} Failures, {5} Possible Candidates", stopwatch.Elapsed, targetWIS.Count, updated, skipped, failures, candidates), this.Name); }
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); }
private List <WorkItem> FilterWorkItemsThatAlreadyExistInTarget(List <WorkItem> sourceWorkItems, WorkItemStoreContext targetStore) { var targetQuery = new TfsQueryContext(targetStore); targetQuery.AddParameter("TeamProject", me.Target.Config.Name); targetQuery.Query = string.Format( @"SELECT [System.Id], [{0}] FROM WorkItems WHERE [System.TeamProject] = @TeamProject ORDER BY [System.ChangedDate] desc", me.Target.Config.ReflectedWorkItemIDFieldName); var targetFoundItems = targetQuery.Execute(); var targetFoundIds = (from WorkItem twi in targetFoundItems select targetStore.GetReflectedWorkItemId(twi, me.Target.Config.ReflectedWorkItemIDFieldName)).ToList(); ////////////////////////////////////////////////////////// sourceWorkItems = sourceWorkItems.Where(p => !targetFoundIds.Any(p2 => p2 == p.Id)).ToList(); return(sourceWorkItems); }
internal override void InternalExecute() { WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.BypassRules); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Config.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(); ////////////////////////////////////////////////// WorkItemLinkOMatic linkomatic = new WorkItemLinkOMatic(); foreach (WorkItem wiSourceL in sourceWIS) { Trace.WriteLine(string.Format("Migrating Links for wiSourceL={0}", wiSourceL.Id), "LinkMigrationContext"); WorkItem wiTargetL = null; try { wiTargetL = targetWitsc.FindReflectedWorkItem(wiSourceL, true); } catch (Exception) { Trace.WriteLine(string.Format("Cannot find twiTargetL matching wiSourceL={0} probably due to missing ReflectedWorkItemID", wiSourceL.Id), "LinkMigrationContext"); } 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"); linkomatic.MigrateLinks(wiSourceL, sourceStore, wiTargetL, targetWitsc); current--; } }
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 ORDER BY [System.ChangedDate] desc"); WorkItemCollection targetWIS = tfsqc.Execute(); Trace.WriteLine(string.Format("Found {0} work items...", targetWIS.Count), Name); int current = targetWIS.Count; int count = 0; int failures = 0; int imported = 0; int skipped = 0; foreach (WorkItem targetWi in targetWIS) { Trace.WriteLine(string.Format("{0} - Fixing: {1}-{2}", current, targetWi.Id, targetWi.Type.Name), Name); // Deside on WIT if (me.WorkItemTypeDefinitions.ContainsKey(targetWi.Type.Name)) { FixHtmlAttachmentLinks(targetWi, me.Source.Collection.Uri.ToString(), me.Target.Collection.Uri.ToString()); } else { Trace.WriteLine("...not supported", Name); skipped++; } current--; count++; Trace.Flush(); } ////////////////////////////////////////////////// stopwatch.Stop(); Trace.WriteLine(string.Format(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds - {1} Items, {2} Imported, {3} Skipped, {4} Failures", stopwatch.Elapsed, targetWIS.Count, imported, skipped, failures), this.Name); }
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() { 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 = null; try { wiTargetL = targetWitsc.FindReflectedWorkItem(wiSourceL, me.ReflectedWorkItemIdFieldName, true); } catch (Exception) { Trace.WriteLine(string.Format("Cannot find twiTargetL matching wiSourceL={0} probably due to missing ReflectedWorkItemID", wiSourceL.Id), "LinkMigrationContext"); } 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"); } } if (wiSourceL.Type.Name == "Test Case") { MigrateSharedSteps(wiSourceL, wiTargetL, sourceStore, targetWitsc); } current--; } }
internal override void InternalExecute() { var stopwatch = Stopwatch.StartNew(); ////////////////////////////////////////////////// var sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.BypassRules); var 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); var sourceWorkItems = tfsqc.Execute(); Trace.WriteLine($"Replay all revisions of {sourceWorkItems.Count} work items?", Name); ////////////////////////////////////////////////// var targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules); var destProject = targetStore.GetProject(); Trace.WriteLine($"Found target project as {destProject.Name}", Name); var current = sourceWorkItems.Count; var count = 0; long elapsedms = 0; //Validation: make sure that the ReflectedWorkItemId field name specified in the config exists in the target process, preferably on each work item type. ConfigValidation(); foreach (WorkItem sourceWorkItem in sourceWorkItems) { var witstopwatch = Stopwatch.StartNew(); var targetFound = targetStore.FindReflectedWorkItem(sourceWorkItem, me.ReflectedWorkItemIdFieldName, false); Trace.WriteLine($"{current} - Migrating: {sourceWorkItem.Id} - {sourceWorkItem.Type.Name}", Name); if (targetFound == null) { ReplayRevisions(sourceWorkItem, destProject, sourceStore, current, targetStore); } else { Console.WriteLine("...Exists"); } sourceWorkItem.Close(); witstopwatch.Stop(); elapsedms += witstopwatch.ElapsedMilliseconds; current--; count++; var average = new TimeSpan(0, 0, 0, 0, (int)(elapsedms / count)); var 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)), Name); Trace.Flush(); } ////////////////////////////////////////////////// stopwatch.Stop(); Console.WriteLine(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed); }
//private void PopulateIgnoreList() // { // _ignore = new List<string>(); // //ignore.Add("System.CreatedDate"); // //ignore.Add("System.CreatedBy"); // _ignore.Add("System.Rev"); // _ignore.Add("System.AreaId"); // _ignore.Add("System.IterationId"); // _ignore.Add("System.Id"); // //ignore.Add("System.ChangedDate"); // //ignore.Add("System.ChangedBy"); // _ignore.Add("System.RevisedDate"); // _ignore.Add("System.AttachedFileCount"); // _ignore.Add("System.TeamProject"); // _ignore.Add("System.NodeName"); // _ignore.Add("System.RelatedLinkCount"); // _ignore.Add("System.WorkItemType"); // _ignore.Add("Microsoft.VSTS.Common.ActivatedDate"); // _ignore.Add("Microsoft.VSTS.Common.StateChangeDate"); // _ignore.Add("System.ExternalLinkCount"); // _ignore.Add("System.HyperLinkCount"); // _ignore.Add("System.Watermark"); // _ignore.Add("System.AuthorizedDate"); // _ignore.Add("System.BoardColumn"); // _ignore.Add("System.BoardColumnDone"); // _ignore.Add("System.BoardLane"); // _ignore.Add("SLB.SWT.DateOfClientFeedback"); // } 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.Id] ", _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; int failures = 0; int imported = 0; int skipped = 0; long elapsedms = 0; foreach (WorkItem sourceWI in sourceWIS) { Stopwatch witstopwatch = new Stopwatch(); witstopwatch.Start(); WorkItem targetWit; targetWit = targetStore.FindReflectedWorkItem(sourceWI, me.ReflectedWorkItemIdFieldName, false); Trace.WriteLine(string.Format("{0} - Migrating: {1}-{2}", current, sourceWI.Id, sourceWI.Type.Name), this.Name); if (targetWit == 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); if (newwit.Fields["System.History"].Value != null) { var history = $"{newwit.Fields["System.History"].Value}"; var witLink = "href=\"x-mvwit:workitem"; var extLink = "href=\"https://dev.azure.com/oemwork"; if (history.Contains(witLink) || history.Contains(extLink)) { history = history.Replace(witLink, string.Empty); history = history.Replace(extLink, string.Empty); newwit.Fields["System.History"].Value = history; } } if (newwit.Fields["System.ChangedBy"].Value.ToString().Contains("Ayuba Audu")) { newwit.Fields["System.ChangedBy"].Value = "wpicustm"; } if (newwit.Fields["System.CreatedBy"].Value.ToString().Contains("Ayuba Audu")) { newwit.Fields["System.CreatedBy"].Value = "wpicustm"; } 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); skipped++; } 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 (!string.IsNullOrWhiteSpace(me.SourceReflectedWorkItemIdFieldName) && sourceWI.Fields.Contains(me.SourceReflectedWorkItemIdFieldName) && _config.UpdateSoureReflectedId) { sourceWI.Fields[me.SourceReflectedWorkItemIdFieldName].Value = targetStore.CreateReflectedWorkItemId(newwit); sourceWI.Save(); } Trace.WriteLine(string.Format("...and Source Updated {0}", sourceWI.Id), this.Name); imported++; } catch (Exception ex) { Trace.WriteLine("...FAILED to Save", this.Name); failures++; 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 if (_config.UpdateTargetIfAlreadyExists) { Trace.WriteLine("Exists. Trying to update with latest snapshot", this.Name); // Deside on WIT if (me.WorkItemTypeDefinitions.ContainsKey(sourceWI.Type.Name)) { targetWit = CreateAndPopulateWorkItem(_config, sourceWI, destProject, me.WorkItemTypeDefinitions[sourceWI.Type.Name].Map(sourceWI), targetWit); me.ApplyFieldMappings(sourceWI, targetWit); if (targetWit.Fields["System.History"].Value != null) { var history = $"{targetWit.Fields["System.History"].Value}"; var witLink = "href=\"x-mvwit:workitem"; var extLink = "href=\"https://dev.azure.com/oemwork"; if (history.Contains(witLink) || history.Contains(extLink)) { history = history.Replace(witLink, string.Empty); history = history.Replace(extLink, string.Empty); targetWit.Fields["System.History"].Value = history; } } if (targetWit.Fields["System.ChangedBy"].Value.ToString().Contains("Ayuba Audu")) { targetWit.Fields["System.ChangedBy"].Value = "wpicustm"; } if (targetWit.Fields["System.CreatedBy"].Value.ToString().Contains("Ayuba Audu")) { targetWit.Fields["System.CreatedBy"].Value = "wpicustm"; } ArrayList fails = targetWit.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); } try { targetWit.Save(); targetWit.Close(); Trace.WriteLine( $" ...Updated {targetWit.Id}.", Name); } catch (Exception e) { Trace.TraceError(e.Message); } } else { Trace.WriteLine("...not supported", this.Name); skipped++; } } else { //Trace.WriteLine("...Exists", this.Name); skipped++; // 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(); Trace.WriteLine(string.Format(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds - {1} Items, {2} Imported, {3} Skipped, {4} Failures", stopwatch.Elapsed, sourceWIS.Count, imported, skipped, failures), this.Name); }
internal override void InternalExecute() { 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 {0}", _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; 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)); List <string> gitWits = new List <string> { "Branch", "Fixed in Commit", "Pull Request" }; foreach (Link l in workitem.Links) { if (l is ExternalLink && gitWits.Contains(l.ArtifactLinkType.Name)) { 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); string oldCommitId = null; string oldGitRepoId = bits[1]; if (bits.Count() >= 3) { oldCommitId = $"{bits[2]}"; for (int i = 3; i < bits.Count(); i++) { oldCommitId += $"%2f{bits[i]}"; } } else { oldCommitId = bits[2]; } var oldGitRepo = (from g in sourceGitRepos where g.Id.ToString() == oldGitRepoId select g) .SingleOrDefault(); if (oldGitRepo != null) { // Find the target git repo GitRepository newGitRepo = null; var repoNameToLookFor = !string.IsNullOrEmpty(_config.TargetRepository) ? _config.TargetRepository : oldGitRepo.Name; // Source and Target project names match if (oldGitRepo.ProjectReference.Name == me.Target.Name) { newGitRepo = (from g in targetGitRepos where g.Name == repoNameToLookFor && g.ProjectReference.Name == oldGitRepo.ProjectReference.Name select g).SingleOrDefault(); } // Source and Target project names do not match else { newGitRepo = (from g in targetGitRepos where g.Name == repoNameToLookFor && g.ProjectReference.Name != oldGitRepo.ProjectReference.Name select g).SingleOrDefault(); } // Fix commit links if target repo has been found if (newGitRepo != null) { Trace.WriteLine($"Fixing {oldGitRepo.RemoteUrl} to {newGitRepo.RemoteUrl}?"); // Create External Link object ExternalLink newLink = null; switch (l.ArtifactLinkType.Name) { case "Branch": newLink = new ExternalLink(targetStore.Store.RegisteredLinkTypes[ArtifactLinkIds.Branch], $"vstfs:///git/ref/{newGitRepo.ProjectReference.Id}%2f{newGitRepo.Id}%2f{oldCommitId}"); break; case "Fixed in Commit": newLink = new ExternalLink(targetStore.Store.RegisteredLinkTypes[ArtifactLinkIds.Commit], $"vstfs:///git/commit/{newGitRepo.ProjectReference.Id}%2f{newGitRepo.Id}%2f{oldCommitId}"); break; case "Pull Request": newLink = new ExternalLink(targetStore.Store.RegisteredLinkTypes[ArtifactLinkIds.PullRequest], $"vstfs:///Git/PullRequestId/{newGitRepo.ProjectReference.Id}%2f{newGitRepo.Id}%2f{oldCommitId}"); break; default: Trace.WriteLine(String.Format("Skipping unsupported link type {0}", l.ArtifactLinkType.Name)); break; } if (newLink != null) { var elinks = from Link lq in workitem.Links where gitWits.Contains(lq.ArtifactLinkType.Name) select(ExternalLink) lq; var found = (from Link lq in elinks where (((ExternalLink)lq).LinkedArtifactUri.ToLower() == newLink.LinkedArtifactUri.ToLower()) select lq).SingleOrDefault(); if (found == null) { newEL.Add(newLink); } removeEL.Add(el); } } else { Trace.WriteLine($"FAIL: cannot map {oldGitRepo.RemoteUrl} to ???"); } } else { Trace.WriteLine($"FAIL could not find source git repo"); noteFound++; } } } // add and remove foreach (ExternalLink eln in newEL) { try { Trace.WriteLine("Adding " + eln.LinkedArtifactUri, Name); workitem.Links.Add(eln); } catch (Exception) { // eat exception as sometimes TFS thinks this is an attachment } } foreach (ExternalLink elr in removeEL) { if (workitem.Links.Contains(elr)) { try { Trace.WriteLine("Removing " + elr.LinkedArtifactUri, Name); workitem.Links.Remove(elr); } catch (Exception) { // eat exception as sometimes TFS thinks this is an attachment } } } if (workitem.IsDirty) { Trace.WriteLine($"Saving {workitem.Id}"); 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); }
//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 = Stopwatch.StartNew(); ////////////////////////////////////////////////// WorkItemStoreContext sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.None); TfsQueryContext tfsqc = new TfsQueryContext(sourceStore); tfsqc.AddParameter("TeamProject", me.Source.Config.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 = Stopwatch.StartNew(); WorkItem targetFound; targetFound = targetStore.FindReflectedWorkItem(sourceWI, 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); }
internal override void InternalExecute() { if (_config == null) { throw new Exception("You must call Configure() first"); } var workItemServer = me.Source.Collection.GetService <WorkItemServer>(); attachmentOMatic = new AttachmentOMatic(workItemServer, _config.AttachmentWorkingPath, _config.AttachmentMazSize); repoOMatic = new RepoOMatic(me); VssClientCredentials adoCreds = new VssClientCredentials(); _witClient = new WorkItemTrackingHttpClient(me.Target.Collection.Uri, adoCreds); //Validation: make sure that the ReflectedWorkItemId field name specified in the config exists in the target process, preferably on each work item type. ConfigValidation(); PopulateIgnoreList(); var stopwatch = Stopwatch.StartNew(); ////////////////////////////////////////////////// var sourceStore = new WorkItemStoreContext(me.Source, WorkItemStoreFlags.BypassRules, Telemetry); var tfsqc = new TfsQueryContext(sourceStore, Telemetry); tfsqc.AddParameter("TeamProject", me.Source.Config.Project); tfsqc.Query = string.Format( @"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY {1}", _config.QueryBit, _config.OrderBit); var sourceQueryResult = tfsqc.Execute(); var sourceWorkItems = (from WorkItem swi in sourceQueryResult select swi).ToList(); contextLog.Information("Replay all revisions of {sourceWorkItemsCount} work items?", sourceWorkItems.Count); ////////////////////////////////////////////////// var targetStore = new WorkItemStoreContext(me.Target, WorkItemStoreFlags.BypassRules, Telemetry); var destProject = targetStore.GetProject(); contextLog.Information("Found target project as {@destProject}", destProject.Name); //////////////////////////////////////////////////////////FilterCompletedByQuery if (_config.FilterWorkItemsThatAlreadyExistInTarget) { sourceWorkItems = FilterWorkItemsThatAlreadyExistInTarget(sourceWorkItems, targetStore); } ////////////////////////////////////////////////// _current = 1; _count = sourceWorkItems.Count; _elapsedms = 0; _totalWorkItem = sourceWorkItems.Count; foreach (WorkItem sourceWorkItem in sourceWorkItems) { workItemLog = contextLog.ForContext("SourceWorkItemId", sourceWorkItem.Id); using (LogContext.PushProperty("sourceWorkItemTypeName", sourceWorkItem.Type.Name)) using (LogContext.PushProperty("currentWorkItem", _current)) using (LogContext.PushProperty("totalWorkItems", _totalWorkItem)) using (LogContext.PushProperty("sourceWorkItemId", sourceWorkItem.Id)) using (LogContext.PushProperty("sourceRevisionInt", sourceWorkItem.Revision)) using (LogContext.PushProperty("targetWorkItemId", null)) { ProcessWorkItem(sourceStore, targetStore, destProject, sourceWorkItem, _config.WorkItemCreateRetryLimit); if (_config.PauseAfterEachWorkItem) { Console.WriteLine("Do you want to continue? (y/n)"); if (Console.ReadKey().Key != ConsoleKey.Y) { workItemLog.Warning("USER ABORTED"); break; } } } } ////////////////////////////////////////////////// stopwatch.Stop(); contextLog.Information("DONE in {Elapsed}", stopwatch.Elapsed.ToString("c")); }
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.Id] ", _config.QueryBit); WorkItemCollection sourceWIS = tfsqc.Execute(); int current = sourceWIS.Count; var workItemServer = me.Source.Collection.GetService <WorkItemServer>(); 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); var attachmentUploadedDate = $"{wia.AttachedTime}"; var attachmentUploaded = attachmentUploadedDate.Replace("/", "--").Replace(":", "+"); // We will create a folder for the work item and place all attachments there. var workitemFolder = reflectedId.Replace("/", "--").Replace(":", "+"); Directory.CreateDirectory(Path.Combine(exportPath, workitemFolder)); var fpath = Path.Combine(exportPath, workitemFolder, $"{attachmentUploaded}@{wia.Name}"); Trace.Write("-"); Trace.Write(fpath); if (!File.Exists(fpath)) { Trace.Write("...downloading"); const int maxRetryCount = 10; var reTryCount = 0; while (reTryCount < maxRetryCount) { reTryCount++; try { var fileLocation = workItemServer.DownloadFile(wia.Id); File.Copy(fileLocation, fpath, true); Trace.Write("...done"); break; } catch (Exception ex) { Telemetry.Current.TrackException(ex); Trace.Write($"\r\n Attempt {reTryCount} of {maxRetryCount} : Exception downloading attachements {ex.Message}"); } } } 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); }