Skip to content
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
3b58ca1
Refactor source generator
igoravl Sep 7, 2025
e2b54a2
Update dependencies
igoravl Sep 8, 2025
32fd4b6
Remove obsolete files
igoravl Sep 9, 2025
56336d2
Update clients
igoravl Sep 9, 2025
84101ad
Refactor tests
igoravl Sep 12, 2025
ef8ba5a
Refactor source generators
igoravl Sep 12, 2025
8be3004
Update Git settings for Verify
igoravl Sep 12, 2025
9b267b8
Refactor src gen
igoravl Sep 14, 2025
df7ede3
Refactor unit tests
igoravl Sep 17, 2025
b81ae80
Refactor generators
igoravl Sep 17, 2025
4252882
Refactor code
igoravl Sep 18, 2025
0520daf
Refactor code
igoravl Sep 19, 2025
51c3914
Update unit tests
igoravl Sep 22, 2025
33e245b
Update source generators
igoravl Sep 22, 2025
a29d79b
Refactor import ctor args
igoravl Sep 22, 2025
8308929
Move class to separate file
igoravl Sep 22, 2025
751dc1e
Optimize usings
igoravl Sep 22, 2025
d4d0c77
Fix property type
igoravl Sep 22, 2025
251524b
Update integration tests
igoravl Sep 23, 2025
73c72c2
Disable cmdlets temporarily
igoravl Sep 23, 2025
892e3a6
Fix invalid cast
igoravl Sep 23, 2025
a77162d
Improve directive
igoravl Sep 23, 2025
3acbc9f
Remove obsolete using directive
igoravl Sep 23, 2025
8ceed33
Refactor source generators
igoravl Sep 23, 2025
191694a
Update dependencies
igoravl Sep 23, 2025
8352038
Fix reference
igoravl Sep 23, 2025
a914073
Add new tests
igoravl Sep 24, 2025
dd767fc
Update unit tests
igoravl Sep 24, 2025
e1ab275
Remove unused methods
igoravl Sep 24, 2025
7cc999c
Add missing line breaks
igoravl Sep 24, 2025
bc0f139
Disable tests for disabled cmdlets
igoravl Sep 24, 2025
f86b183
Move to shared project
igoravl Sep 24, 2025
d1c04c9
Update unit tests
igoravl Sep 24, 2025
1e77eb4
Fix typo
igoravl Sep 24, 2025
125b51d
Add unit test execution
igoravl Sep 24, 2025
b4ecc8e
Add default solution path to VSCode settings
igoravl Sep 26, 2025
2dddcfb
Merge branch 'main' into refactor-src-gen
igoravl Apr 9, 2026
ff24377
Update unit tests
igoravl Apr 9, 2026
5be1496
Update target frameworks to net472 and enhance Azure credential manag…
igoravl Apr 9, 2026
ccaed4f
Fix InstallerUrl to use ThreePartVersion for MSI download
igoravl Apr 10, 2026
de22ea5
Update release notes
igoravl Apr 10, 2026
43fd654
Update tests
igoravl Apr 11, 2026
cce78df
Enhance RemoveGitRepository cmdlet to support irreversible deletion w…
igoravl Apr 11, 2026
1d620b6
Update CI/CD pipeline configuration from main.yml to build.yml
igoravl Apr 11, 2026
f2c0f8d
Remove special-case code handling for areas, iterations and tags
igoravl Apr 11, 2026
b5f7815
Fix typo
igoravl Apr 11, 2026
38b0d75
Add changelog guidelines to AGENTS.md
igoravl Apr 11, 2026
f74c818
Add missing source-gen tests
igoravl Apr 11, 2026
9e31e9f
Enhance cmdlet addition instructions with source generator unit test …
igoravl Apr 11, 2026
405b4f6
Add AzureLogin properties to ControllerInfo for parameter handling
igoravl Apr 11, 2026
33a76a4
Add documentation on discovering available API methods in HttpClient …
igoravl Apr 11, 2026
2ba24a3
Add -Deleted switch parameter to Get-TfsGitRepository for listing del…
igoravl Apr 11, 2026
d8e8e7e
Add Undo-TfsGitRepositoryRemoval cmdlet to restore deleted Git reposi…
igoravl Apr 11, 2026
08b8ae3
Refactor Git repository handling in cmdlets to improve deletion and r…
igoravl Apr 11, 2026
5e6aa1b
Updates release notes
igoravl Apr 11, 2026
907d1cd
Fix work item field cmdlets
igoravl Apr 11, 2026
ab38070
Fix variable declaration
igoravl Apr 11, 2026
64b1be6
Update release notes
igoravl Apr 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 11 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,14 @@ root = true
[*.cs]

dotnet_diagnostic.IDE0056.severity = none
dotnet_diagnostic.IDE0057.severity = none
dotnet_diagnostic.IDE0057.severity = none

# Verify settings
[*.{received,verified}.{json,txt,xml,cs}]
charset = utf-8-bom
end_of_line = lf
indent_size = unset
indent_style = unset
insert_final_newline = false
tab_width = unset
trim_trailing_whitespace = false
10 changes: 10 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
###############################################################################
* text=auto

###############################################################################
# Verify settings
###############################################################################

*.verified.txt text eol=lf working-tree-encoding=UTF-8
*.verified.xml text eol=lf working-tree-encoding=UTF-8
*.verified.json text eol=lf working-tree-encoding=UTF-8
*.verified.cs text eol=lf working-tree-encoding=UTF-8
Comment on lines +10 to +13

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Verify file normalization rules set working-tree-encoding=UTF-8, but .editorconfig sets Verify artifacts to charset = utf-8-bom. These conflict and can cause persistent churn (files rewritten with/without BOM depending on tooling). Align the encoding policy: either set .editorconfig to utf-8 (no BOM) or change .gitattributes to working-tree-encoding=UTF-8-BOM (and confirm your Git version supports it) so Verify snapshots have stable bytes.

Suggested change
*.verified.txt text eol=lf working-tree-encoding=UTF-8
*.verified.xml text eol=lf working-tree-encoding=UTF-8
*.verified.json text eol=lf working-tree-encoding=UTF-8
*.verified.cs text eol=lf working-tree-encoding=UTF-8
*.verified.txt text eol=lf working-tree-encoding=UTF-8-BOM
*.verified.xml text eol=lf working-tree-encoding=UTF-8-BOM
*.verified.json text eol=lf working-tree-encoding=UTF-8-BOM
*.verified.cs text eol=lf working-tree-encoding=UTF-8-BOM

Copilot uses AI. Check for mistakes.
*.verified.bin binary

###############################################################################
# Set default behavior for command prompt diff.
#
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,15 @@ TfsCmdlets.PSDesktop.xml

CSharp/.idea/**

# Verify files

*.received.*
*.received/

# Miscellaneous files

CSharp/*/Generated/**
Docs/AzDO-Security-Actions.csv
**/testResults.xml
PS/_Tests/coverage.xml
CSharp/**/Old/**
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.color": "Indigo",
"dotnet.preferCSharpExtension": false
"dotnet.preferCSharpExtension": false,
"dotnet.defaultSolution": "CSharp/TfsCmdlets.sln"
}
2 changes: 1 addition & 1 deletion CSharp/TfsCmdlets.Legacy/TfsCmdlets.Legacy.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<PackageReference Include="Microsoft.VisualStudio.Services.Search.Client" Version="16.*-*" />
<PackageReference Include="Microsoft.VisualStudio.Services.ServiceEndpoints.WebApi" Version="16.*-*" />
<PackageReference Include="Microsoft.VisualStudio.Services.ServiceHooks.WebApi" Version="16.*-*" />
<PackageReference Include="PowerShellStandard.Library" Version="7.0.0-preview.1" PrivateAssets="all" />
<PackageReference Include="PowerShellStandard.Library" Version="5.*" PrivateAssets="all" />
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
<PackageReference Include="System.Composition" Version="5.0.1" />
<PackageReference Include="System.Composition.Hosting" Version="5.0.1" />
Expand Down
28 changes: 28 additions & 0 deletions CSharp/TfsCmdlets.Shared/CmdletControllerAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace TfsCmdlets {

[AttributeUsage(System.AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public sealed class CmdletControllerAttribute : ExportAttribute
{
public Type DataType { get; }

public string CustomCmdletName { get; set; }

public string[] CustomVerbs { get; set; }

public string[] CustomNouns { get; set; }

public Type CustomBaseClass { get; set; }

public Type Client { get; set; }


public CmdletControllerAttribute() : base(typeof(IController))
{
}

public CmdletControllerAttribute(Type dataType) : base(typeof(IController))
{
DataType = dataType;
}
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace TfsCmdlets.Cmdlets.WorkItem.AreasIterations
{
internal abstract class CopyClassificationNodeController: ControllerBase
public abstract class CopyClassificationNodeController: ControllerBase
{
protected override IEnumerable Run()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace TfsCmdlets.Cmdlets.WorkItem.AreasIterations
{
internal abstract class GetClassificationNodeController: ControllerBase
public abstract class GetClassificationNodeController: ControllerBase
{
private INodeUtil NodeUtil { get; set; }

Expand Down Expand Up @@ -81,7 +81,7 @@ protected override IEnumerable Run()
}

[ImportingConstructor]
protected GetClassificationNodeController(INodeUtil nodeUtil, IPowerShellService powerShell, IDataManager data, IParameterManager parameters, ILogger logger, IWorkItemTrackingHttpClient client)
protected GetClassificationNodeController(INodeUtil nodeUtil, IWorkItemTrackingHttpClient client, IPowerShellService powerShell, IDataManager data, IParameterManager parameters, ILogger logger)
: base(powerShell, data, parameters, logger)
{
NodeUtil = nodeUtil;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace TfsCmdlets.Cmdlets.WorkItem.AreasIterations
{
internal abstract class MoveClassificationNodeController : ControllerBase
public abstract class MoveClassificationNodeController : ControllerBase
{
private IWorkItemTrackingHttpClient Client { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace TfsCmdlets.Cmdlets.WorkItem.AreasIterations
{
internal abstract class NewClassificationNodeController: ControllerBase
public abstract class NewClassificationNodeController: ControllerBase
{
private INodeUtil NodeUtil { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace TfsCmdlets.Cmdlets.WorkItem.AreasIterations
{
internal abstract class RemoveClassificationNodeController: ControllerBase
public abstract class RemoveClassificationNodeController: ControllerBase
{
private IWorkItemTrackingHttpClient Client { get; set; }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TfsCmdlets.Cmdlets.WorkItem.AreasIterations
{
internal abstract class TestClassificationNodeController: ControllerBase
public abstract class TestClassificationNodeController: ControllerBase
{
protected override IEnumerable Run()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace TfsCmdlets.Cmdlets.WorkItem.Tagging
{
internal abstract class ToggleWorkItemTagController: ControllerBase
public abstract class ToggleWorkItemTagController: ControllerBase
{
[Import]
private ITaggingHttpClient Client { get; set; }
Expand All @@ -16,9 +16,12 @@
foreach (var tag in tags)
{
if (!PowerShell.ShouldProcess(tp, $"{(enabled? "Enable": "Disable")} work item tag '{tag.Name}'")) continue;

yield return Client.UpdateTagAsync(tp.Id, tag.Id, tag.Name, enabled)
.GetResult($"Error renaming work item tag '{tag.Name}'");
#if UNIT_TEST_PROJECT
yield break;
#else
yield return Client.UpdateTagAsync(tp.Id, tag.Id, tag.Name, enabled)

Check warning on line 22 in CSharp/TfsCmdlets.Shared/Cmdlets/WorkItem/Tagging/ToggleWorkItemTagController.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This line will not be executed conditionally; only the first line of this 5-line block will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=igoravl_TfsCmdlets&issues=AZ0xDeaCP8bj0kFn1OQ_&open=AZ0xDeaCP8bj0kFn1OQ_&pullRequest=253
.GetResult($"Error renaming work item tag '{tag.Name}'");
#endif

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under UNIT_TEST_PROJECT, yield break; exits the entire controller on the first eligible tag, which changes control-flow compared to production (it won’t iterate remaining tags). If the goal is to avoid hitting the HTTP client during tests while preserving iteration behavior, prefer continue; (skip the update but keep looping) or yield a deterministic placeholder result so multi-tag scenarios behave consistently.

Copilot uses AI. Check for mistakes.
}
}

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TfsCmdlets.HttpClients
namespace TfsCmdlets
{
internal class HttpClientAttribute : Attribute
public sealed class HttpClientAttribute : Attribute
Comment on lines +1 to +3

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving HttpClientAttribute out of the TfsCmdlets.HttpClients namespace will break all [HttpClient(...)] usages inside namespace TfsCmdlets.HttpClients unless those files have using TfsCmdlets; (or fully qualify the attribute). Since these interface files typically have no using directives, this is very likely a compile break. Either keep the attribute in TfsCmdlets.HttpClients, or update the attribute usages (or add a global using) to reference TfsCmdlets.HttpClientAttribute.

Copilot uses AI. Check for mistakes.
{
public HttpClientAttribute(Type type)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(AccountLicensingHttpClient))]
partial interface IAccountLicensingHttpClient
public partial interface IAccountLicensingHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(BuildHttpClient))]
partial interface IBuildHttpClient
public partial interface IBuildHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(ExtensionManagementHttpClient))]
partial interface IExtensionManagementHttpClient
public partial interface IExtensionManagementHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients {

[HttpClient(typeof(FeedHttpClient))]
partial interface IFeedHttpClient {
public partial interface IFeedHttpClient {

}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(GenericHttpClient))]

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written, [HttpClient(...)] is no longer resolvable here after HttpClientAttribute was moved to namespace TfsCmdlets (parent namespaces aren’t automatically in scope). This will fail to compile unless a using TfsCmdlets; (or a global using) is present. Prefer fully qualifying the attribute or restoring the attribute’s original namespace to prevent widespread edits across interface files.

Suggested change
[HttpClient(typeof(GenericHttpClient))]
[TfsCmdlets.HttpClient(typeof(GenericHttpClient))]

Copilot uses AI. Check for mistakes.
partial interface IGenericHttpClient
public partial interface IGenericHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(GitExtendedHttpClient))]
partial interface IGitExtendedHttpClient
public partial interface IGitExtendedHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(GitHttpClient))]
partial interface IGitHttpClient
public partial interface IGitHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(GraphHttpClient))]
partial interface IGraphHttpClient
public partial interface IGraphHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(IdentityHttpClient))]
partial interface IIdentityHttpClient
public partial interface IIdentityHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients {

[HttpClient(typeof(OperationsHttpClient))]
partial interface IOperationsHttpClient {
public partial interface IOperationsHttpClient {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(PolicyHttpClient))]
partial interface IPolicyHttpClient
public partial interface IPolicyHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(ProcessHttpClient))]
partial interface IProcessHttpClient {
public partial interface IProcessHttpClient {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(ProjectHttpClient))]
partial interface IProjectHttpClient
public partial interface IProjectHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(ReleaseHttpClient))]
partial interface IReleaseHttpClient
public partial interface IReleaseHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(ReleaseHttpClient2))]
partial interface IReleaseHttpClient2
public partial interface IReleaseHttpClient2
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(SearchHttpClient))]
partial interface ISearchHttpClient
public partial interface ISearchHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(ServiceHooksPublisherHttpClient))]
partial interface IServiceHooksPublisherHttpClient
public partial interface IServiceHooksPublisherHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(TaggingHttpClient))]
partial interface ITaggingHttpClient
public partial interface ITaggingHttpClient
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients
{
[HttpClient(typeof(TeamAdminHttpClient))]
partial interface ITeamAdminHttpClient
public partial interface ITeamAdminHttpClient
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace TfsCmdlets.HttpClients {

[HttpClient(typeof(TeamHttpClient))]
partial interface ITeamHttpClient
public partial interface ITeamHttpClient
{
}
}
Loading
Loading