@@ -30,10 +30,12 @@ internal static void MigrateCapacities(
3030 try
3131 {
3232 var sourceTeamContext = new TeamContext ( sourceProjectId , sourceTeam . Identity . TeamFoundationId ) ;
33- var sourceIterations = sourceHttpClient . GetTeamIterationsAsync ( sourceTeamContext ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
33+ var sourceIterations = sourceHttpClient . GetTeamIterationsAsync ( sourceTeamContext )
34+ . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
3435
3536 var targetTeamContext = new TeamContext ( targetProjectId , targetTeam . Identity . TeamFoundationId ) ;
36- var targetIterations = targetHttpClient . GetTeamIterationsAsync ( targetTeamContext ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
37+ var targetIterations = targetHttpClient . GetTeamIterationsAsync ( targetTeamContext )
38+ . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
3739
3840 foreach ( var sourceIteration in sourceIterations )
3941 {
@@ -43,74 +45,14 @@ internal static void MigrateCapacities(
4345 var targetIteration = targetIterations . FirstOrDefault ( i => i . Path == targetIterationPath ) ;
4446 if ( targetIteration == null ) continue ;
4547
46- var targetCapacities = new List < TeamMemberCapacityIdentityRef > ( ) ;
47- var sourceCapacities = sourceHttpClient . GetCapacitiesWithIdentityRefAsync ( sourceTeamContext , sourceIteration . Id ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
48- foreach ( var sourceCapacity in sourceCapacities )
49- {
50- var sourceDisplayName = sourceCapacity . TeamMember . DisplayName ;
51- var index = sourceDisplayName . IndexOf ( "<" ) ;
52- if ( index > 0 )
53- {
54- sourceDisplayName = sourceDisplayName . Substring ( 0 , index ) . Trim ( ) ;
55- }
56-
57- // Match:
58- // "Doe, John" to "Doe, John"
59- // "John Doe" to "John Doe"
60- var targetTeamFoundatationIdentity = identityCache . Value . FirstOrDefault ( i => i . DisplayName == sourceDisplayName ) ;
61- if ( targetTeamFoundatationIdentity == null )
62- {
63- if ( sourceDisplayName . Contains ( ", " ) )
64- {
65- // Match:
66- // "Doe, John" to "John Doe"
67- var splitName = sourceDisplayName . Split ( ',' ) ;
68- sourceDisplayName = $ "{ splitName [ 1 ] . Trim ( ) } { splitName [ 0 ] . Trim ( ) } ";
69- targetTeamFoundatationIdentity = identityCache . Value . FirstOrDefault ( i => i . DisplayName == sourceDisplayName ) ;
70- }
71- else
72- {
73- if ( sourceDisplayName . Contains ( ' ' ) )
74- {
75- // Match:
76- // "John Doe" to "Doe, John"
77- var splitName = sourceDisplayName . Split ( ' ' ) ;
78- sourceDisplayName = $ "{ splitName [ 1 ] . Trim ( ) } , { splitName [ 0 ] . Trim ( ) } ";
79- targetTeamFoundatationIdentity = identityCache . Value . FirstOrDefault ( i => i . DisplayName == sourceDisplayName ) ;
80- }
81- }
82-
83- // last attempt to match on unique name
84- // Match: "John Michael Bolden" to Bolden, "John Michael" on "[email protected] " unique name 85- if ( targetTeamFoundatationIdentity == null )
86- {
87- var sourceUniqueName = sourceCapacity . TeamMember . UniqueName ;
88- targetTeamFoundatationIdentity = identityCache . Value . FirstOrDefault ( i => i . UniqueName == sourceUniqueName ) ;
89- }
90- }
91-
92- if ( targetTeamFoundatationIdentity != null )
93- {
94- targetCapacities . Add ( new TeamMemberCapacityIdentityRef
95- {
96- Activities = sourceCapacity . Activities ,
97- DaysOff = sourceCapacity . DaysOff ,
98- TeamMember = new IdentityRef
99- {
100- Id = targetTeamFoundatationIdentity . TeamFoundationId . ToString ( )
101- }
102- } ) ;
103- }
104- else
105- {
106- log . LogWarning ( "[SKIP] Team Member {member} was not found on target when replacing capacities on iteration {iteration}." , sourceCapacity . TeamMember . DisplayName , targetIteration . Path ) ;
107- }
108- }
48+ List < TeamMemberCapacityIdentityRef > sourceCapacities = GetSourceCapacities (
49+ sourceHttpClient , sourceTeamContext , sourceIteration ) ;
50+ List < TeamMemberCapacityIdentityRef > targetCapacities = GetTargetCapacities (
51+ sourceCapacities , targetIteration . Path , identityCache , log ) ;
10952
11053 if ( targetCapacities . Count > 0 )
11154 {
112- targetHttpClient . ReplaceCapacitiesWithIdentityRefAsync ( targetCapacities , targetTeamContext , targetIteration . Id ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
113- log . LogDebug ( "Team {team} capacities for iteration {iteration} migrated." , targetTeam . Name , targetIteration . Path ) ;
55+ ReplaceTargetCapacities ( targetHttpClient , targetTeamContext , targetTeam , targetIteration , targetCapacities , log ) ;
11456 }
11557 }
11658 catch ( Exception ex )
@@ -128,5 +70,109 @@ internal static void MigrateCapacities(
12870
12971 log . LogInformation ( "Team capacities migration done.." ) ;
13072 }
73+
74+ private static List < TeamMemberCapacityIdentityRef > GetSourceCapacities (
75+ WorkHttpClient sourceHttpClient ,
76+ TeamContext sourceTeamContext ,
77+ TeamSettingsIteration sourceIteration )
78+ {
79+ return sourceHttpClient . GetCapacitiesWithIdentityRefAsync ( sourceTeamContext , sourceIteration . Id )
80+ . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
81+ }
82+
83+ private static List < TeamMemberCapacityIdentityRef > GetTargetCapacities (
84+ List < TeamMemberCapacityIdentityRef > sourceCapacities ,
85+ string targetIteration ,
86+ Lazy < List < TeamFoundationIdentity > > identityCache ,
87+ ILogger log )
88+ {
89+ var targetCapacities = new List < TeamMemberCapacityIdentityRef > ( ) ;
90+ foreach ( var sourceCapacity in sourceCapacities )
91+ {
92+ if ( TryMatchIdentity ( sourceCapacity , identityCache , out TeamFoundationIdentity targetIdentity ) )
93+ {
94+ targetCapacities . Add ( new TeamMemberCapacityIdentityRef
95+ {
96+ Activities = sourceCapacity . Activities ,
97+ DaysOff = sourceCapacity . DaysOff ,
98+ TeamMember = new IdentityRef
99+ {
100+ Id = targetIdentity . TeamFoundationId . ToString ( )
101+ }
102+ } ) ;
103+ }
104+ else
105+ {
106+ log . LogWarning ( "[SKIP] Team Member {member} was not found on target when replacing capacities "
107+ + "on iteration {iteration}." , sourceCapacity . TeamMember . DisplayName , targetIteration ) ;
108+ }
109+ }
110+
111+ return targetCapacities ;
112+ }
113+
114+ private static void ReplaceTargetCapacities (
115+ WorkHttpClient targetHttpClient ,
116+ TeamContext targetTeamContext ,
117+ TeamFoundationTeam targetTeam ,
118+ TeamSettingsIteration targetIteration ,
119+ List < TeamMemberCapacityIdentityRef > targetCapacities ,
120+ ILogger log )
121+ {
122+ targetHttpClient . ReplaceCapacitiesWithIdentityRefAsync ( targetCapacities , targetTeamContext , targetIteration . Id )
123+ . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
124+ log . LogDebug ( "Team {team} capacities for iteration {iteration} migrated." , targetTeam . Name , targetIteration . Path ) ;
125+ }
126+
127+ private static bool TryMatchIdentity (
128+ TeamMemberCapacityIdentityRef sourceCapacity ,
129+ Lazy < List < TeamFoundationIdentity > > identityCache ,
130+ out TeamFoundationIdentity targetIdentity )
131+ {
132+ var sourceDisplayName = sourceCapacity . TeamMember . DisplayName ;
133+ var index = sourceDisplayName . IndexOf ( "<" ) ;
134+ if ( index > 0 )
135+ {
136+ sourceDisplayName = sourceDisplayName . Substring ( 0 , index ) . Trim ( ) ;
137+ }
138+
139+ // Match:
140+ // "Doe, John" to "Doe, John"
141+ // "John Doe" to "John Doe"
142+ targetIdentity = identityCache . Value . FirstOrDefault ( i => i . DisplayName == sourceDisplayName ) ;
143+ if ( targetIdentity == null )
144+ {
145+ if ( sourceDisplayName . Contains ( ", " ) )
146+ {
147+ // Match:
148+ // "Doe, John" to "John Doe"
149+ var splitName = sourceDisplayName . Split ( ',' ) ;
150+ sourceDisplayName = $ "{ splitName [ 1 ] . Trim ( ) } { splitName [ 0 ] . Trim ( ) } ";
151+ targetIdentity = identityCache . Value . FirstOrDefault ( i => i . DisplayName == sourceDisplayName ) ;
152+ }
153+ else
154+ {
155+ if ( sourceDisplayName . Contains ( ' ' ) )
156+ {
157+ // Match:
158+ // "John Doe" to "Doe, John"
159+ var splitName = sourceDisplayName . Split ( ' ' ) ;
160+ sourceDisplayName = $ "{ splitName [ 1 ] . Trim ( ) } , { splitName [ 0 ] . Trim ( ) } ";
161+ targetIdentity = identityCache . Value . FirstOrDefault ( i => i . DisplayName == sourceDisplayName ) ;
162+ }
163+ }
164+
165+ // last attempt to match on unique name
166+ // Match: "John Michael Bolden" to Bolden, "John Michael" on "[email protected] " unique name 167+ if ( targetIdentity == null )
168+ {
169+ var sourceUniqueName = sourceCapacity . TeamMember . UniqueName ;
170+ targetIdentity = identityCache . Value . FirstOrDefault ( i => i . UniqueName == sourceUniqueName ) ;
171+ }
172+ }
173+
174+ return targetIdentity is not null ;
175+ }
131176 }
132177}
178+
0 commit comments