Add `rbt install` command for installing dependencies.

Review Request #8294 — Created July 18, 2016 and submitted

Information

RBTools
release-0.7.x
c06909a...

Reviewers

In some cases, we want to be able to install extra dependencies on-demand
instead of shipping everything with RBTools. The current example of this is
that we're pulling the TFS interface out into our own custom-written helper
(instead of making everyone download Team Explorer Everywhere), but it's too
big to just include in the egg.

With this new command, users can download and install said dependencies in one
command. This doesn't attempt to be a full-fledged package manager (there's no
versioning, or dependencies, or conflict resolution, etc), but it should be
good enough.

This does make some efforts to verify that the downloaded package is authentic.
If gpg is installed, it will check that the file is correctly signed.
Otherwise, it will check the sha256sum.

Used this a bunch while iterating on the TFS module. Checked that both
signature and sha256sum validation worked as expected.

Description From Last Updated

local variable 'gpg_dir' is assigned to but never used

reviewbotreviewbot

Col: 80 E501 line too long (81 > 79 characters)

reviewbotreviewbot

Swap these.

chipx86chipx86

"RBTools"

chipx86chipx86

Missing period.

chipx86chipx86

Let's place this in its own directory on downloads.beanbaginc.com. That'll make it easier for our stuff to manage the files.

chipx86chipx86

No need for the [].

chipx86chipx86

Period after sentences in comments, here and below.

chipx86chipx86

Trying to decide.... since these log entries (particularly the logging.info ones) are being output to the terminal, should we have …

chipx86chipx86

%s instead of +

chipx86chipx86

We should delete this before we raise CommandError above.

chipx86chipx86

Let's use %s instead of +. We also need to catch HTTPError and URLError for this. Particularly important when dealing …

chipx86chipx86

We should probably sanity-check this, and raise an error if we're not seeing what we expect. Might want to sanity-check …

chipx86chipx86

Let's put more information in here, say what hash we expected and what we got, specify the URL, and explain …

chipx86chipx86

We should either delete this when aborting above, or specify the location so that users can handle/refer to it.

chipx86chipx86

We should have try/except to catch any IOError or OSError from this.

chipx86chipx86

We need to catch here too, in case permissions are wrong (or something like SELinux gets in the way).

chipx86chipx86

Need to catch URLError and HTTPError here. (Or maybe the caller should do it? In which case, the docstring should …

chipx86chipx86

The description must be indented for exceptions.

chipx86chipx86

Can we wrap the line at the \n? We could maybe start the string indented 4 spaces from the raise, …

chipx86chipx86

Blank line between these.

chipx86chipx86

This can be while read_bytes != total_bytes:, instead of having that at the end.

chipx86chipx86

Needs the full module path.

chipx86chipx86

Newlines don't work so well in debug output. Subsequent lines don't get the prefix. Let's make each of these lines …

chipx86chipx86
reviewbot
  1. Tool: Pyflakes
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
    
    Tool: PEP8 Style Checker
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
  2. rbtools/commands/install.py (Diff revision 1)
     
     
    Show all issues
     local variable 'gpg_dir' is assigned to but never used
    
  3. 
      
david
reviewbot
  1. Tool: Pyflakes
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
    
    Tool: PEP8 Style Checker
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
  2. rbtools/commands/install.py (Diff revision 2)
     
     
    Show all issues
    Col: 80
     E501 line too long (81 > 79 characters)
    
  3. 
      
gmyers
  1. 
      
  2. rbtools/commands/install.py (Diff revision 2)
     
     
    Looking at other commands, it seems like this should be enclosed in brackets for consistency: <package>
  3. 
      
david
reviewbot
  1. Tool: PEP8 Style Checker
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
    
    Tool: Pyflakes
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
  2. 
      
chipx86
  1. 
      
  2. rbtools/commands/install.py (Diff revision 3)
     
     
     
    Show all issues

    Swap these.

  3. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    "RBTools"

  4. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    Missing period.

  5. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    Let's place this in its own directory on downloads.beanbaginc.com. That'll make it easier for our stuff to manage the files.

  6. rbtools/commands/install.py (Diff revision 3)
     
     
     
     
     
    Show all issues

    No need for the [].

  7. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    Period after sentences in comments, here and below.

  8. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    Trying to decide.... since these log entries (particularly the logging.info ones) are being output to the terminal, should we have these in sentence format, with a period at the end?

    RBTools logging.info and CommandError-based output generally do unless doing My message: %s. I kinda feel that'd be the right thing to do.

    1. I'll do it for the ones that print but not the logging.debug ones.

  9. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    %s instead of +

  10. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    We should delete this before we raise CommandError above.

  11. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    Let's use %s instead of +.

    We also need to catch HTTPError and URLError for this. Particularly important when dealing with proxies.

    Should we use download_file for this?

    1. I initially used download_file but it's overkill since we really don't care about having the file saved to disk and then we have to delete it.

  12. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    We should probably sanity-check this, and raise an error if we're not seeing what we expect.

    Might want to sanity-check the length of the real_sha as well.

    1. I don't think we really need to check it here because if it's not what we expect, it won't match the sum that we compute below, and we'll show an error there.

  13. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    Let's put more information in here, say what hash we expected and what we got, specify the URL, and explain what this means (the file might not be safe).

    1. I'm not sure spitting out two 64-character hashes is really useful at all to anyone.

  14. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    We should either delete this when aborting above, or specify the location so that users can handle/refer to it.

  15. rbtools/commands/install.py (Diff revision 3)
     
     
     
     
     
     
    Show all issues

    We should have try/except to catch any IOError or OSError from this.

  16. rbtools/commands/install.py (Diff revision 3)
     
     
     
     
     
    Show all issues

    We need to catch here too, in case permissions are wrong (or something like SELinux gets in the way).

  17. rbtools/commands/install.py (Diff revision 3)
     
     
    Show all issues

    Need to catch URLError and HTTPError here. (Or maybe the caller should do it? In which case, the docstring should specify that those can raise.)

  18. 
      
david
reviewbot
  1. Tool: Pyflakes
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
    
    Tool: PEP8 Style Checker
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
  2. 
      
chipx86
  1. 
      
  2. rbtools/commands/install.py (Diff revision 4)
     
     
     
    Show all issues

    The description must be indented for exceptions.

  3. rbtools/commands/install.py (Diff revision 4)
     
     
    Show all issues

    Can we wrap the line at the \n? We could maybe start the string indented 4 spaces from the raise, like above.

    It'd also be nice to specify the signatures (expected and actual), so the user can compare themselves if needed, and report to us. Would particularly help if there's an issue of some sort with the file contents from an upload.

    1. I don't really think it's that useful to spew out 128 characters of junk, especially since the files themselves will have been removed after the command exits. A user "comparing it themselves" will say "yep, those are different" but it won't mean anything and there won't be anything they can do about it.

      If there's a problem with the upload, there's no difference between them reporting it to us, and I would hope that we'd test the installation any time we upload the files anyway.

    2. It'd be nice to have something that we can inspect, at least. Perhaps log output showing the SHAs + pointing to the file paths in a temp directory, so that we can have them send us data on them.

      Plenty of things can go wrong that aren't necessarily our fault. Proxy issues causing bad content, some S3 error payload due to something going wrong, MITM (which would be useful to inspect). If something does go wrong, we should know about it, and we'll need useful information to help with that.

      What we could do is log the SHAs and the file paths as a CRITICAL and, in the error message, say to report this to us along with the contents of the files mentioned.

    3. Are you saying you want me to undo the work to ensure things are deleted on cleanup?

    4. Hmm.. Kinda contradictory, isn't it... No, I think the work was good and should be kept, and takes care of the other cases where things might fail but state was left behind.

      I guess we can always have them manually download the file in a browser or something if we need to debug it. It'd still be good to have the SHAs in the debug log so we can verify that RBTools is getting the same thing the browser's getting (helping to diagnose proxy issues or something). So I guess my only ask would be including the SHAs in the debug output.

  4. rbtools/commands/install.py (Diff revision 4)
     
     
     
    Show all issues

    Blank line between these.

  5. rbtools/commands/install.py (Diff revision 4)
     
     
    Show all issues

    This can be while read_bytes != total_bytes:, instead of having that at the end.

  6. 
      
david
reviewbot
  1. Tool: PEP8 Style Checker
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
    
    Tool: Pyflakes
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
  2. 
      
chipx86
  1. 
      
  2. rbtools/commands/install.py (Diff revision 5)
     
     
    Show all issues

    Needs the full module path.

  3. 
      
david
reviewbot
  1. Tool: PEP8 Style Checker
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
    
    Tool: Pyflakes
    Processed Files:
        setup.py
        rbtools/commands/install.py
    
    
  2. 
      
chipx86
  1. 
      
  2. rbtools/commands/install.py (Diff revisions 5 - 6)
     
     
     
     
    Show all issues

    Newlines don't work so well in debug output. Subsequent lines don't get the prefix. Let's make each of these lines a logging.debug().

  3. 
      
david
Review request changed
Status:
Completed
Change Summary:
Pushed to release-0.7.x (a84c507)