From 5027931bf7d3f4fb1d89894b305c461c727be635 Mon Sep 17 00:00:00 2001 From: pombredanne Date: Sat, 4 Jul 2015 16:41:02 +0200 Subject: [PATCH] Reject running scancode --extract with other options. * also added cli tests --- .travis.yml | 2 +- src/scancode/cli.py | 33 +++++-- .../data/copyright/copyright_acme_c-c.c | 1 + tests/scancode/data/extract/some.tar.gz | Bin 0 -> 596 bytes tests/scancode/data/license/apache-1.0.txt | 55 +++++++++++ tests/scancode/test_cli.py | 90 ++++++++++++++++++ 6 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 tests/scancode/data/copyright/copyright_acme_c-c.c create mode 100644 tests/scancode/data/extract/some.tar.gz create mode 100644 tests/scancode/data/license/apache-1.0.txt create mode 100644 tests/scancode/test_cli.py diff --git a/.travis.yml b/.travis.yml index ecff4723b90..a6db53a1075 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,5 +7,5 @@ install: - source configure script: - - py.test -n 2 -vs src tests/commoncode tests/extractcode tests/textcode tests/typecode tests/cluecode tests/licensedcode/test_detect.py tests/licensedcode/test_index.py tests/licensedcode/test_legal.py tests/licensedcode/test_models.py + - py.test -n 2 -vs src tests/commoncode tests/extractcode tests/textcode tests/typecode tests/cluecode tests/scancode tests/licensedcode/test_detect.py tests/licensedcode/test_index.py tests/licensedcode/test_legal.py tests/licensedcode/test_models.py diff --git a/src/scancode/cli.py b/src/scancode/cli.py index cd4b3181a5a..227a745e183 100644 --- a/src/scancode/cli.py +++ b/src/scancode/cli.py @@ -39,7 +39,6 @@ from scancode.api import get_licenses from scancode.api import HtmlAppAssetCopyWarning from scancode.api import HtmlAppAssetCopyError -import textwrap info_text = ''' @@ -187,19 +186,32 @@ def print_version(ctx, param, value): ''' +short_help = '''Usage: scancode [OPTIONS] +Try 'scancode --help' for more information.''' + + formats = ['json', 'html', 'html-app'] + class ScanCommand(click.Command): """ Workaround click 4.0 bug https://github.com/mitsuhiko/click/issues/365 """ def get_usage(self, ctx): - formatted = '''Usage: scancode [OPTIONS] -Try 'scancode --help' for more information''' - return formatted + return short_help + + +def validate_extract(ctx, param, value): + if not value or ctx.resilient_parsing: + return + click.echo(ctx.params) + ctx.fail('''The '--extract' option cannot be combined with other scanning options. +Use '--extract' alone to extract, then run a scan on the extracted files.''') + ctx.exit() @click.command(name='scancode', epilog=epilog_text, cls=ScanCommand) +@click.pass_context @click.argument('input', metavar='', type=click.Path(exists=True, readable=True)) @click.argument('output_file', default='-', metavar='', type=click.File('wb')) @click.option('-c', '--copyright', is_flag=True, default=False, help='Scan for copyrights. [default]') @@ -218,23 +230,30 @@ def get_usage(self, ctx): @click.option('--verbose', is_flag=True, default=False, help='Show verbose scan progress messages.') @click.option('--version', is_flag=True, is_eager=True, callback=print_version, help=('Show the version and exit.')) -def scancode(input, output_file, extract, copyright, license, format, verbose, *args, **kwargs): +def scancode(ctx, input, output_file, extract, copyright, license, format, verbose, *args, **kwargs): """scan the file or directory for origin and license and save results to the . The scan results are printed on terminal if is not provided. """ + scans = [copyright, license] if extract: + if any(scans): + # exclusive, ignoring other options. + # FIXME: this should turned into a sub-command + ctx.fail('''The '--extract' option cannot be combined with other scanning options. +Use '--extract' alone to extract , then run a scan on the extracted files.''') + ctx.exit(1) + click.secho('Extracting archives...', fg='green') extract_errors = get_extract(input) if extract_errors: # FIXME: Provide a better way to report errors and we need to report progress click.secho('\n'.join(extract_errors), fg='red') click.secho('Extracting done.', fg='green') - # exclusive, ignoring other options. return # Default scan when no options is provided - if not any((copyright, license)): + if not any(scans): copyright = True license = True diff --git a/tests/scancode/data/copyright/copyright_acme_c-c.c b/tests/scancode/data/copyright/copyright_acme_c-c.c new file mode 100644 index 00000000000..23dbd722d5d --- /dev/null +++ b/tests/scancode/data/copyright/copyright_acme_c-c.c @@ -0,0 +1 @@ +/* Copyright © 2000 ACME, Inc., All Rights Reserved */ \ No newline at end of file diff --git a/tests/scancode/data/extract/some.tar.gz b/tests/scancode/data/extract/some.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..904ce06d81f1fc1ad511c64eb1f7647d2ed15679 GIT binary patch literal 596 zcmV-a0;~NWiwFSaYX4LK1MS$|ZrU&$hhZ*-gPp?s5y!_=1r@2FNw5oWQ}eOX7}=S$ z-u)a-Ikc7mlzzeklqn@Y5L{dY)IS&e?UVmG2=IVN8Rw?NM7BbDNO^k45kKb@mA zV?t(vWZ8gFP6Zzf#ZCU2Pky>e+2L?-G_OxqKdZ9T7k_VQ8czJ*)ZhIV)AeLDU(R}6 z2qFDBb^BnzCXzpJbb8x+^f}sBOd75)Z(LaT@ z{{DRDH4xUH`To*>i~cEG)4x*g$lIaYg9szcyH2;To06Ffuz z6yo|jw+mPUA@_e&*8Mq0|1{$JPo7+5RZ*?nZlRr1Tm6NOi-U6R^Lqr}|8u_s;Ql{} zUi*KuW^4WHg(>%yvG1!Pygz3dNBL)q_qN(p4I4tl=RcmKe-fSgugw+HA9ejdJ^w}j+v}(QzotKG{z-=ZNp$GH zdbm@rW%N%XKL6$Zfc^<|>OcLZi>8OZA4K$*c>b40=l(aEf10Cz3Z43YciPU&jp_gS ikAH#w00000000000000000000*Z2)J5#lufPyhf2&p The Apache Group. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + "This product includes software developed by the Apache Group + for use in the Apache HTTP server project (http://www.apache.org/)." + + 4. The names "Apache Server" and "Apache Group" must not be used to + endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache" + nor may "Apache" appear in their names without prior written + permission of the Apache Group. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes software developed by the Apache Group + for use in the Apache HTTP server project (http://www.apache.org/)." + + THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. +==================================================================== + + This software consists of voluntary contributions made by many + individuals on behalf of the Apache Group and was originally based + on public domain software written at the National Center for + Supercomputing Applications, University of Illinois, Urbana-Champaign. + For more information on the Apache Group and the Apache HTTP server + project, please see . + \ No newline at end of file diff --git a/tests/scancode/test_cli.py b/tests/scancode/test_cli.py new file mode 100644 index 00000000000..5f523eb22bc --- /dev/null +++ b/tests/scancode/test_cli.py @@ -0,0 +1,90 @@ +# +# Copyright (c) 2015 nexB Inc. and others. All rights reserved. +# http://nexb.com and https://github.com/nexB/scancode-toolkit/ +# The ScanCode software is licensed under the Apache License version 2.0. +# Data generated with ScanCode require an acknowledgment. +# ScanCode is a trademark of nexB Inc. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# When you publish or redistribute any data created with ScanCode or any ScanCode +# derivative work, you must accompany this data with the following acknowledgment: +# +# Generated with ScanCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES +# OR CONDITIONS OF ANY KIND, either express or implied. No content created from +# ScanCode should be considered or used as legal advice. Consult an Attorney +# for any legal advice. +# ScanCode is a free software code scanning tool from nexB Inc. and others. +# Visit https://github.com/nexB/scancode-toolkit/ for support and download. + +from __future__ import absolute_import, print_function + +import os + +from click.testing import CliRunner + +from commoncode.testcase import FileBasedTesting +from scancode import cli + + +class TestCommandLine(FileBasedTesting): + test_data_dir = os.path.join(os.path.dirname(__file__), 'data') + + def test_extract_option_is_exclusive_of_other_options(self): + test_dir = self.get_temp_dir() + runner = CliRunner() + result = runner.invoke(cli.scancode, ['--extract', '--copyright', test_dir]) + assert result.exit_code == 2 + assert 'option cannot be combined with other scanning options' in result.output + + result = runner.invoke(cli.scancode, ['--copyright', '--extract', test_dir]) + assert result.exit_code == 2 + assert 'option cannot be combined with other scanning options' in result.output + + result = runner.invoke(cli.scancode, ['--extract', '--license', test_dir]) + assert result.exit_code == 2 + assert 'option cannot be combined with other scanning options' in result.output + + result = runner.invoke(cli.scancode, ['--extract', '--license', '--copyright', test_dir]) + assert result.exit_code == 2 + assert 'option cannot be combined with other scanning options' in result.output + + def test_extract_option_can_take_an_empty_directory(self): + test_dir = self.get_temp_dir() + runner = CliRunner() + result = runner.invoke(cli.scancode, ['--extract', test_dir]) + assert result.exit_code == 0 + assert 'Extracting done' in result.output + + def test_extract_option_does_extract(self): + test_dir = self.get_test_loc('extract', copy=True) + runner = CliRunner() + result = runner.invoke(cli.scancode, ['--extract', test_dir]) + assert result.exit_code == 0 + assert 'Extracting done' in result.output + assert os.path.exists(os.path.join(test_dir, 'some.tar.gz-extract')) + + def test_copyright_option_detects_copyrights(self): + test_dir = self.get_test_loc('copyright', copy=True) + runner = CliRunner() + output_json = self.get_temp_file('json') + result = runner.invoke(cli.scancode, ['--copyright', test_dir, output_json]) + assert result.exit_code == 0 + assert 'Scanning done' in result.output + assert os.path.exists(output_json) + assert len(open(output_json).read()) > 10 + + def test_license_option_detects_licenses(self): + test_dir = self.get_test_loc('license', copy=True) + runner = CliRunner() + output_json = self.get_temp_file('json') + result = runner.invoke(cli.scancode, ['--license', test_dir, output_json]) + assert result.exit_code == 0 + assert 'Scanning done' in result.output + assert os.path.exists(output_json) + assert len(open(output_json).read()) > 10