Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to link multiple referenced packages at once #27

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

danieljbfaustino
Copy link

Fixes #6

Tool can now be run with:

  • nulink link -r [repos_root_dir] - if run on the solution's (.sln) directory, will link all referenced packages in all projects within the solution. If run on the project's (.csproj) directory, will link all referenced packages in such project. The user only needs to provide the directory where all repositories are located to the -r option.
  • nulink unlink - if run without options, it will unlink all packages from solution/project, depending on where command is ran.

Copy link
Member

@felix-b felix-b left a comment

Choose a reason for hiding this comment

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

Hi @danieljbfaustino, this is a great addition to the tool, thanks again! I want it merged.

Yet this isn't a trivial feature, and it has a few tricky aspects, which we have to sort out first - please see my comments below.

I also suggested a couple of styling improvements (I am really sorry for being meticulous - I'm guarding the code to be readable and clean).

Last but not least, we have to add tests that cover the new functionality before we can merge it. The relevant files are LinkTests.cs and UnlinkTests.cs, these are acceptance tests that actually invoke the tool. I'm going to write a document on these, but I can't promise when. Let me know if you need guidance.

I think this is a great feature that pushes the tool to the next level. But if the effort to complete it seems overwhelming, and maybe you didn't plan to invest that much, just let me know - I will continue from where you stop. This PR is a good first step.

@@ -2,6 +2,6 @@ namespace NuLink.Cli
{
public interface INuLinkCommand
{
int Execute(NuLinkCommandOptions options);
void Execute(NuLinkCommandOptions options);
Copy link
Member

Choose a reason for hiding this comment

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

The idea behind the int return value is to return an exit code, which can be useful for scripting. I guess int becomes tricky because of a multi-package operation, which can result in a mix of successes and failures. In such a case, I'd prefer to define the overall success and failure.

This is what I suggest:

  • For link command, the "package already linked" situation, when the link target is the desired location, should be a success rather than an error (print a success message, do nothing).
  • For unlink command, if the package is not linked, it's a success and not an error (print a success message, do nothing).
  • Continue to handle all other errors
  • Let the user choose one of two modes:
    • Fail fast (default): stop on the first error and exit with an error code
    • Ignore errors: if an --ignore-errors flag is specified, we run all packages, report all errors as warnings, and always exit with code 0.

(as for implementation, see comment below about exceptions)

var allPackages = GetAllPackages(options);
var localProjectPath = options.LocalProjectPath;

if (options.Mode != NuLinkCommandOptions.LinkMode.AllToAll)
Copy link
Member

Choose a reason for hiding this comment

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

A styling hint: in order to keep functions short, I'd extract "then" and "else" into two nested functions.

}

void ValidateOperation()
bool ValidateOperation()
Copy link
Member

Choose a reason for hiding this comment

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

TL;DR: let's keep throwing exceptions rather than returning a bool.

I was thinking quite a bit about this one. If we want to support both "ignore errors" and "fail fast" modes, the code can become complicated. I mean that using exception results in simpler code. On the other hand, we have "do not use exceptions to steer logic".

In the bottom line, I think that throwing exceptions from LinkPackage() is OK, because LinkPackage should either perform its responsibility or throw. We can implement both "fail fast" and "ignore" by catching at the caller (inside the foreach loop). When in "ignore" mode, report a warning. When in "fail fast" mode, re-throw.


if (options.Mode == NuLinkCommandOptions.LinkMode.SingleToAll)
{
localProjectPath = GetAllProjects(options.RootDirectory).
Copy link
Member

Choose a reason for hiding this comment

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

I'd avoid reassigning a local variable because it reduces readability.

Instead, you can introduce a new variable named effectiveLocalProjectPath and use the ? : operator to assign it either localProjectPath or the result of lookup with GetAllProjects().

}

if (status.IsLibFolderLinked)
{
throw new Exception($"Error: Package {requestedPackage.PackageId} is already linked to {status.LibFolderLinkTargetPath}");
_ui.Report(singleMode ? VerbosityLevel.Error : VerbosityLevel.Low, () =>
Copy link
Member

Choose a reason for hiding this comment

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

As I wrote above, this should be an error only if the link target path differs from the requested one. Maybe this check should be performed earlier.

{
throw new Exception($"Error: Cannot unlink package {options.PackageId}: 'lib' folder not found, expected {requestedPackage.LibFolderPath}");
_ui.Report(allPackages ? VerbosityLevel.Low : VerbosityLevel.Error, () =>
Copy link
Member

Choose a reason for hiding this comment

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

Let's make it always a success.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add ability to link multiple referenced packages at once
2 participants