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 Export/Import commands #699

Merged
merged 35 commits into from
Feb 13, 2021
Merged

Add Export/Import commands #699

merged 35 commits into from
Feb 13, 2021

Conversation

florelis
Copy link
Member

@florelis florelis commented Jan 13, 2021

This implements a prototype of the import and export commands. Opening as draft to gather feedback on schema and command options.
Overview of changes:

  • Added a schema for a list of packages in JSON format. This lists packages (id, version, channel) and the sources they come from (name, arg, type, id).
  • Export command with syntax winget export [--output] file.json [common query filters]. This creates a list of the matching packages. Packages that are not available from any source are still listed so that they can be imported if they are added later to a source.
  • Import command with syntax winget import [--input] file.json [--exactVersions]. This installs all the packages from a list. Each package is installed from the source listed from it, unless there is no source specified in which case it is taken from any available. Installs latest version, unless the --exactVersions flag is used.

Still missing tests & resource strings.

Related: #155, #156, #220

Microsoft Reviewers: Open in CodeFlow

@florelis florelis requested a review from a team January 13, 2021 22:54
Copy link
Member

@JohnMcPMS JohnMcPMS left a comment

Choose a reason for hiding this comment

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

We need to ensure that everyone is on the same page about the direction here before more work is done. Some of my comments may not apply afterward, but I have given feedback based on how I expect export/import to work.

doc/packages.schema.json Outdated Show resolved Hide resolved
doc/packages.schema.json Outdated Show resolved Hide resolved
src/AppInstallerCLICore/Argument.cpp Outdated Show resolved Hide resolved
src/AppInstallerCLICore/Commands/ExportCommand.cpp Outdated Show resolved Hide resolved
src/AppInstallerCLICore/Commands/ImportCommand.cpp Outdated Show resolved Hide resolved
src/AppInstallerCLICore/Workflows/ImportExportFlow.cpp Outdated Show resolved Hide resolved

context << OpenNamedSource(requiredSource.Details.Name);
auto source = context.Get<Execution::Data::Source>();
aggregatedSource->AddAvailableSource(source);
Copy link
Member

Choose a reason for hiding this comment

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

This pattern does not force the source to actually be used for a given package, which is what we want. The goal should be that if a package should come from a specific source, then that source should be used exclusively. Otherwise, the standard unnamed source (all combined) should be used.

Copy link
Member Author

Choose a reason for hiding this comment

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

This pattern does not force the source to actually be used for a given package

What do you mean?

Copy link
Member

Choose a reason for hiding this comment

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

You are finding source 1, then adding it to the aggregate, then searching. All of these packages will come from the correct source.

Then you find source 2, add it to the aggregate, and search. These packages could be coming from source 1 or 2.

You should simply open the source and use it for the packages in question. No need to use the aggregate.

Copy link
Member Author

Choose a reason for hiding this comment

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

When I do the search, I'm not doing it in context which has the aggregate, but in searchContext which only has the individual source, so it should use only that one source unless I'm missing something.

I'm using the aggregate because some step of the installation (can't remember which atm) references the package's source so we need to keep it alive somehow (as the package has only a weak reference). Maybe keeping it as the root context's Source was not the best idea, more so since the composite source wasn't intended to be public. I can change it to keep around the sources as a list in the context.

But this all depends on me wanting to do all the searches before installing. If we change it to searching right before each install as you say, the aggregate can go away.

Execution::Context& searchContext = *searchContextPtr;
searchContext.Add<Execution::Data::Source>(source);

// TODO: Case insensitive?
Copy link
Member

Choose a reason for hiding this comment

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

Finding the appropriate package and version to install is going to be far more complex than this. We may not have the Id handy; we may just have the name and publisher and will require the ability to find something based on that.

But I think that having a review on the spec and schema will help solidify the requirements.


// Extract the data needed for installing
installContext.Add<Execution::Data::PackageVersion>(package);
installContext.Add<Execution::Data::Manifest>(package->GetManifest());
Copy link
Member

Choose a reason for hiding this comment

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

Is there not already a workflow task that does this step?

Copy link
Member Author

Choose a reason for hiding this comment

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

There is a GetManifest task but it does more work than is needed here (e.g. checking the arguments and using them to select the version). Here we want to seed the sub context with info we already have so that it can start doing its work.

@ghost ghost added Needs-Author-Feedback Issue needs attention from issue or PR author and removed Needs-Author-Feedback Issue needs attention from issue or PR author labels Jan 14, 2021
Luis Enrique Chacon Ochoa added 7 commits January 21, 2021 12:22
* Made source details required in schema.
* Stopped using CompositeSource in ImportFlow and instead moved to keeping a list of sources in the context.
* Stopped selecting version to export from available ones, and instead always use installed one, warning if it is not available.
* Stopped exporting unavailable packages.
* Stopped allowing to import packages with no source.
* Use existing code to select version to install.
* Moved strings for JSON from .h to .cpp
* Renamed PackageRequest class
@github-actions
Copy link

New misspellings found, please review:

  • noversion
  • validator
  • valijson
  • withversion
To accept these changes, run the following commands
perl -e '
my @expect_files=qw('".github/actions/spelling/expect.txt"');
@ARGV=@expect_files;
my @stale=qw('"AComment addressof ALIGNAS allescaped alse ARMEL backend bbwe bitfield blep BORLAND cassert cctype cdunn cerr clocale CMake cmath cname codepoint cplusplus CPPLIB cstddef cstdio cstdlib cstr cstring CStyle ctor czstring deque deref dllimport dnp elif emark endcode endverbatim EOL eturn eyc fpclassify gcc GNUC hpux HREF hrow ieeefp inl iosfwd isfinite Isfinitef isnan isprint IString javascript jsonvalue keey keylength lconv len Lepilleur localeconv lossfree malloc maxsize memcmp memset MINGW modf msvc Multiline mutators nfinity noreturn NULLREF nvcc NVIDIAs OString ote ptrdiff py Skype skypeapp Solaris sourceforge sout SOVERSION ssin stackoverflow STARTUPINFOW stdarg strchr strcmp strdup strlen strncmp unindent Unserialize usf Utils valueiterator vscprintf vsnprintf walkaround wiki wikipedia Workaround wstringstream xf xl "');
my $re=join "|", @stale;
my $suffix=".".time();
my $previous="";
sub maybe_unlink { unlink($_[0]) if $_[0]; }
while (<>) {
  if ($ARGV ne $old_argv) { maybe_unlink($previous); $previous="$ARGV$suffix"; rename($ARGV, $previous); open(ARGV_OUT, ">$ARGV"); select(ARGV_OUT); $old_argv = $ARGV; }
  next if /^($re)(?:$| .*)/; print;
}; maybe_unlink($previous);'
perl -e '
my $new_expect_file=".github/actions/spelling/expect.txt";
open FILE, q{<}, $new_expect_file; chomp(my @words = <FILE>); close FILE;
my @add=qw('"noversion utils validator valijson withversion "');
my %items; @items{@words} = @words x (1); @items{@add} = @add x (1);
@words = sort {lc($a) cmp lc($b)} keys %items;
open FILE, q{>}, $new_expect_file; for my $word (@words) { print FILE "$word\n" if $word =~ /\w/; };
close FILE;'
git add .github/actions/spelling || echo '... you want to ensure .github/actions/spelling/expect.txt is added to your repository...'


std::optional<PackageCollection> ParseJson(const Json::Value& root)
{
// TODO: Embed schema in binaries & validate file
Copy link
Member Author

Choose a reason for hiding this comment

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

I had some trouble getting this to work. @yao-msft is also working on something with JSON schemas and seems to have this figured out, so I'll wait for him to check in his change and then hook this up with his code.

@florelis florelis requested a review from JohnMcPMS February 2, 2021 02:34
@florelis florelis marked this pull request as ready for review February 2, 2021 02:35
@github-actions
Copy link

github-actions bot commented Feb 3, 2021

New misspellings found, please review:

  • wcout
  • wofstream
  • wostream
To accept these changes, run the following commands
perl -e '
my @expect_files=qw('".github/actions/spelling/expect.txt"');
@ARGV=@expect_files;
my @stale=qw('"AComment addressof ALIGNAS allescaped alse ARMEL backend bbwe bitfield blep BORLAND cassert cctype cdunn cerr clocale CMake cmath cname codepoint cplusplus CPPLIB cstddef cstdio cstdlib cstr cstring CStyle ctor czstring deque deref dllimport dnp elif emark endcode endverbatim EOL eturn eyc fpclassify gcc GNUC hpux HREF hrow ieeefp inl iosfwd isfinite Isfinitef isnan isprint IString javascript jsonvalue keey keylength lconv len Lepilleur localeconv lossfree malloc maxsize memcmp memset MINGW modf msvc Multiline mutators nfinity noreturn NULLREF nvcc NVIDIAs OString ote ptrdiff py Skype skypeapp Solaris sourceforge sout SOVERSION ssin stackoverflow STARTUPINFOW stdarg strchr strcmp strdup strlen strncmp unindent Unserialize usf validator valijson valueiterator vscprintf vsnprintf walkaround wiki wikipedia Workaround xf xl "');
my $re=join "|", @stale;
my $suffix=".".time();
my $previous="";
sub maybe_unlink { unlink($_[0]) if $_[0]; }
while (<>) {
  if ($ARGV ne $old_argv) { maybe_unlink($previous); $previous="$ARGV$suffix"; rename($ARGV, $previous); open(ARGV_OUT, ">$ARGV"); select(ARGV_OUT); $old_argv = $ARGV; }
  next if /^($re)(?:$| .*)/; print;
}; maybe_unlink($previous);'
perl -e '
my $new_expect_file=".github/actions/spelling/expect.txt";
open FILE, q{<}, $new_expect_file; chomp(my @words = <FILE>); close FILE;
my @add=qw('"wcout wofstream wostream "');
my %items; @items{@words} = @words x (1); @items{@add} = @add x (1);
@words = sort {lc($a) cmp lc($b)} keys %items;
open FILE, q{>}, $new_expect_file; for my $word (@words) { print FILE "$word\n" if $word =~ /\w/; };
close FILE;'
git add .github/actions/spelling || echo '... you want to ensure .github/actions/spelling/expect.txt is added to your repository...'

@JohnMcPMS
Copy link
Member

New misspellings found, please review:

  • wcout
  • wofstream
  • wostream

The presence of these suggests misuse; neither our production code nor our tests should be using (w)cout directly. [Although I do frequently do some local debugging of tests with them.]

@github-actions
Copy link

github-actions bot commented Feb 8, 2021

Misspellings found, please review:

  • wstringstream
To accept these changes, run the following commands from this repository on this branch
pushd $(git rev-parse --show-toplevel)
perl -e '
my @expect_files=qw('".github/actions/spelling/expect.txt"');
@ARGV=@expect_files;
my @stale=qw('"validator valijson valueiterator "');
my $re=join "|", @stale;
my $suffix=".".time();
my $previous="";
sub maybe_unlink { unlink($_[0]) if $_[0]; }
while (<>) {
  if ($ARGV ne $old_argv) { maybe_unlink($previous); $previous="$ARGV$suffix"; rename($ARGV, $previous); open(ARGV_OUT, ">$ARGV"); select(ARGV_OUT); $old_argv = $ARGV; }
  next if /^(?:$re)(?:(?:\r|\n)*$| .*)/; print;
}; maybe_unlink($previous);'
perl -e '
my $new_expect_file=".github/actions/spelling/expect.txt";
use File::Path qw(make_path);
make_path ".github/actions/spelling";
open FILE, q{<}, $new_expect_file; chomp(my @words = <FILE>); close FILE;
my @add=qw('"wstringstream "');
my %items; @items{@words} = @words x (1); @items{@add} = @add x (1);
@words = sort {lc($a) cmp lc($b)} keys %items;
open FILE, q{>}, $new_expect_file; for my $word (@words) { print FILE "$word\n" if $word =~ /\w/; };
close FILE;'
popd

@@ -450,6 +450,7 @@ VOS
vso
wapproj
wchar
wcout
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

This is not in the product code or tests directly, but in a standalone .exe used as a test installer. It was mixing narrow and wide chars and that was getting complicated, but it didn't seem worth it to add conversion between them there, so I moved it all to wide. It should be fine as it's independent of everything else.

Copy link
Contributor

Choose a reason for hiding this comment

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

The only thing I'd note is that by using it here instead of, e.g. just telling the bot to ignore the file entirely, the bot will never warn about the next violation.

Think of it like page-fault protection.

Obviously reviewers are responsible for the content, so in theory some reviewer should catch future incursions.

(Just feedback from the peanut gallery.)

src/AppInstallerCLICore/Commands/ImportCommand.cpp Outdated Show resolved Hide resolved
src/AppInstallerCLICore/Workflows/WorkflowBase.cpp Outdated Show resolved Hide resolved
src/AppInstallerCLITests/TestSource.h Show resolved Hide resolved
src/AppInstallerRepositoryCore/CompositeSource.h Outdated Show resolved Hide resolved
@ghost ghost added Needs-Author-Feedback Issue needs attention from issue or PR author and removed Needs-Author-Feedback Issue needs attention from issue or PR author labels Feb 11, 2021
Copy link
Member

@JohnMcPMS JohnMcPMS left a comment

Choose a reason for hiding this comment

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

Just want to clarify how version should be handled by default, as I believe that wanting a specific version is a bit of an edge case (at least wanting a specific version of every package). So I think that export should not include the version, but allow for it with a flag. And import should probably just have flag more like --ignoreVersions that will ignore every version rather than allow fallback to latest in some cases.

src/AppInstallerCLICore/Commands/ImportCommand.cpp Outdated Show resolved Hide resolved
src/AppInstallerCLICore/Workflows/ImportExportFlow.cpp Outdated Show resolved Hide resolved
@ghost ghost added the Needs-Author-Feedback Issue needs attention from issue or PR author label Feb 12, 2021
@ghost ghost removed the Needs-Author-Feedback Issue needs attention from issue or PR author label Feb 12, 2021
@quangkieu
Copy link

@JohnMcPMS how about by default is >= export version. User could add the top limit

version.get(),
channel.get());
// but take the exported version from the installed package if needed.
if (context.Args.Contains(Execution::Args::Type::IncludeVersions))
Copy link
Member

Choose a reason for hiding this comment

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

I think we could be more efficient above if we inspected this flag to prevent the need to even match on an available version.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to do that.

@florelis florelis merged commit 009e684 into microsoft:master Feb 13, 2021
@denelon denelon linked an issue Mar 4, 2021 that may be closed by this pull request
@florelis florelis deleted the ImportExport branch April 2, 2021 23:21
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.

Export/Import apps list
4 participants