:maxdepth: 2
deploy
+ license
nexus
openstack
sign
--- /dev/null
+*******
+License
+*******
+
+.. program-output:: lftools license --help
+
+Commands
+========
+
+.. contents:: License Commands
+ :local:
+
+check
+-----
+
+.. program-output:: lftools license check --help
from lftools.cli.deploy import deploy
from lftools.cli.jenkins import jenkins_cli
+from lftools.cli.license import license
from lftools.cli.nexus import nexus
from lftools.cli.sign import sign
from lftools.cli.version import version
cli.add_command(deploy)
cli.add_command(jenkins_cli, name='jenkins')
+cli.add_command(license)
cli.add_command(nexus)
cli.add_command(openstack)
cli.add_command(sign)
--- /dev/null
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+"""Scan code for license headers."""
+
+__author__ = 'Thanh Ha'
+
+
+import sys
+
+import click
+
+from lftools.license import check_license
+from lftools.license import check_license_directory
+
+
+@click.group()
+@click.pass_context
+def license(ctx):
+ """Scan code for license headers."""
+ pass
+
+
+@click.command()
+@click.argument('source')
+@click.option('-l', '--license', default='license-header.txt',
+ help='License header file to compare against.')
+@click.pass_context
+def check(ctx, license, source):
+ """Check files for missing license headers.
+
+ Does not care if about line formatting of the license as long as all of the
+ text is there and in the correct order.
+
+ Note: This code only supports '#' comments for license headers.
+ """
+ exit_code = check_license(license, source)
+ sys.exit(exit_code)
+
+
+@click.command(name='check-dir')
+@click.argument('directory')
+@click.option('-e', '--extension', default='py',
+ help='File extension to search for.')
+@click.option('-l', '--license', default='license-header.txt',
+ help='License header file to compare against.')
+@click.pass_context
+def check_directory(ctx, license, directory, extension):
+ """Check directory for files missing license headers.
+
+ Does not care if about line formatting of the license as long as all of the
+ text is there and in the correct order.
+
+ Note: This code only supports '#' comments for license headers.
+ """
+ check_license_directory(license, directory, extension)
+
+
+license.add_command(check)
+license.add_command(check_directory)
--- /dev/null
+# -*- coding: utf-8 -*-
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+"""Scans code for a valid license header."""
+
+__author__ = 'Thanh Ha'
+
+
+import os
+import re
+import sys
+
+
+def get_header_text(_file):
+ """Scan a file and pulls out the license header.
+
+ Returns a string containing the license header with newlines and copyright
+ lines stripped.
+
+ Note: This function only supports '#' comments for license headers.
+ """
+ text = ''
+ with open(_file, 'r') as data:
+ lines = data.readlines()
+ for line in lines:
+ result = re.search(r'\s*[#]', line)
+ if not result:
+ break
+ string = re.sub(r'^\s*#+', '', line).strip()
+ if bool(re.match('Copyright', string, re.I)): # Ignore the Copyright line
+ continue
+ text += ' {}'.format(string)
+ # Strip unnecessary spacing
+ text = re.sub('\s+', ' ', text).strip()
+ return text
+
+
+def check_license(license_file, code_file):
+ """Compare a file with the provided license header.
+
+ Reports if license header is missing or does not match the text of
+ license_file.
+ """
+ license_header = get_header_text(license_file)
+ code_header = get_header_text(code_file)
+
+ if not license_header in code_header:
+ print('ERROR: {} is missing or has incorrect license header.'.format(code_file))
+ return 1
+
+ return 0
+
+
+def check_license_directory(license_file, directory, extension="py"):
+ """Search a directory for files and calls check_license()."""
+ missing_license = False
+
+ for root, dirs, files in os.walk(directory):
+ for file in files:
+ if file.endswith(".{}".format(extension)):
+ if check_license(license_file, os.path.join(root, file)):
+ missing_license = True
+
+ if missing_license:
+ sys.exit(1)
+
+ print('Scan completed did not detect any files missing license headers.')
--- /dev/null
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# COPYRIGHT
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
--- /dev/null
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# COPYRIGHT
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
--- /dev/null
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+"""Test code file with license header."""
--- /dev/null
+"""Test code file without license header."""
--- /dev/null
+"""Test code file without license header."""
--- /dev/null
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+"""Test license command."""
+
+import os
+
+import pytest
+
+from lftools import cli
+
+FIXTURE_DIR = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ 'fixtures',
+ )
+
+
+@pytest.mark.datafiles(
+ os.path.join(FIXTURE_DIR, 'license'),
+ )
+def test_check_license(cli_runner, datafiles):
+ """Test check_license() command."""
+ os.chdir(str(datafiles))
+
+ # Check that license checker passes when file has license.
+ result = cli_runner.invoke(cli.cli, ['license', 'check', 'license.py'])
+ # noqa: B101 .
+ assert result.exit_code == 0
+
+ # Check that license checker fails when file is missing license.
+ result = cli_runner.invoke(cli.cli, ['license', 'check', 'no_license1.py'])
+ # noqa: B101 .
+ assert result.exit_code == 1
+
+
+@pytest.mark.datafiles(
+ os.path.join(FIXTURE_DIR, 'license'),
+ )
+def test_check_license_directory(cli_runner, datafiles):
+ """Test check_license_directory() command."""
+ os.chdir(str(datafiles))
+
+ # Check that check-dir fails due to directory containing files
+ # with no license.
+ result = cli_runner.invoke(cli.cli, ['license', 'check-dir', '.'])
+ # noqa: B101 .
+ assert result.exit_code == 1
+
+ # Check that check-dir passes when directory contains files with licenses
+ os.remove('no_license1.py')
+ os.remove('no_license2.py')
+ result = cli_runner.invoke(cli.cli, ['license', 'check-dir', '.'])
+ # noqa: B101 .
+ assert result.exit_code == 0