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 support to ev-cli for custom license headers #168

Merged
merged 4 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ev-dev-tools/src/ev_cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""EVerest command line utility."""
__version__ = '0.4.2'
__version__ = '0.4.3'
41 changes: 31 additions & 10 deletions ev-dev-tools/src/ev_cli/ev.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,25 @@ def generate_module_loader_files(rel_mod_dir, output_dir):
return loader_files


def generate_module_files(rel_mod_dir, update_flag):
def generate_module_files(rel_mod_dir, update_flag, licenses):
(_, _, mod) = rel_mod_dir.rpartition('/')

mod_files = {'core': [], 'interfaces': [], 'docs': []}
mod_path = work_dir / f'modules/{rel_mod_dir}/manifest.yaml'
mod_def = helpers.load_validated_module_def(mod_path, validators['module'])

default_license_dir = Path(__file__).parent / 'licenses'
current_license_dir = work_dir / 'licenses'
additional_license_dir = Path(licenses)
license_dirs = [default_license_dir, current_license_dir, additional_license_dir]
license_url = mod_def['metadata']['license']
license_header = helpers.get_license_header(license_dirs, license_url)

if not license_header:
print(f'Could not find license "{license_url}" in {license_dirs}.')
print('Consider providing a additonal custom license directory with --licenses')
exit(1)

tmpl_data = generate_tmpl_data_for_module(mod, mod_def)
output_path = mod_path.parent
# FIXME (aw): we might move the following function into generate_tmp_data_for_module
Expand Down Expand Up @@ -362,6 +374,7 @@ def generate_module_files(rel_mod_dir, update_flag):

if_tmpl_data['info']['blocks'] = helpers.load_tmpl_blocks(
impl_hpp_blocks, output_path / impl_hpp_file, update_flag)
if_tmpl_data['info']['license_header'] = license_header

# FIXME (aw): time stamp should include parent interfaces modification dates
mod_files['interfaces'].append({
Expand All @@ -370,7 +383,8 @@ def generate_module_files(rel_mod_dir, update_flag):
'printable_name': impl_hpp_file,
'content': templates['interface_impl.hpp'].render(if_tmpl_data),
'template_path': Path(templates['interface_impl.hpp'].filename),
'last_mtime': last_mtime
'last_mtime': last_mtime,
'license_header': license_header
})

mod_files['interfaces'].append({
Expand All @@ -379,11 +393,13 @@ def generate_module_files(rel_mod_dir, update_flag):
'printable_name': impl_cpp_file,
'content': templates['interface_impl.cpp'].render(if_tmpl_data),
'template_path': Path(templates['interface_impl.cpp'].filename),
'last_mtime': last_mtime
'last_mtime': last_mtime,
'license_header': license_header
})

cmakelists_file = output_path / 'CMakeLists.txt'
tmpl_data['info']['blocks'] = helpers.load_tmpl_blocks(cmakelists_blocks, cmakelists_file, update_flag)
tmpl_data['info']['license_header'] = license_header
mod_files['core'].append({
'abbr': 'cmakelists',
'path': cmakelists_file,
Expand All @@ -401,7 +417,8 @@ def generate_module_files(rel_mod_dir, update_flag):
'path': mod_hpp_file,
'content': templates['module.hpp'].render(tmpl_data),
'template_path': Path(templates['module.hpp'].filename),
'last_mtime': mod_path.stat().st_mtime
'last_mtime': mod_path.stat().st_mtime,
'license_header': license_header
})

# module.cpp
Expand All @@ -411,7 +428,8 @@ def generate_module_files(rel_mod_dir, update_flag):
'path': mod_cpp_file,
'content': templates['module.cpp'].render(tmpl_data),
'template_path': Path(templates['module.cpp'].filename),
'last_mtime': mod_path.stat().st_mtime
'last_mtime': mod_path.stat().st_mtime,
'license_header': license_header
})

# doc.rst
Expand Down Expand Up @@ -521,7 +539,7 @@ def generate_interface_headers(interface, all_interfaces_flag, output_dir):
def module_create(args):
create_strategy = 'force-create' if args.force else 'create'

mod_files = generate_module_files(args.module, False)
mod_files = generate_module_files(args.module, False, args.licenses)

if args.only == 'which':
helpers.print_available_mod_files(mod_files)
Expand Down Expand Up @@ -551,7 +569,7 @@ def module_update(args):
update_strategy[file_name] = primary_update_strategy

# FIXME (aw): refactor out this only handling and rename it properly
mod_files = generate_module_files(args.module, True)
mod_files = generate_module_files(args.module, True, args.licenses)

if args.only == 'which':
helpers.print_available_mod_files(mod_files)
Expand All @@ -568,13 +586,13 @@ def module_update(args):
helpers.clang_format(args.clang_format_file, file_info)

for file_info in mod_files['core']:
helpers.write_content_to_file(file_info, update_strategy[file_info['abbr']], args.diff)
helpers.write_content_to_file(file_info, update_strategy[file_info['abbr']], args.diff, '', True)

for file_info in mod_files['interfaces']:
if file_info['abbr'].endswith('.hpp'):
helpers.write_content_to_file(file_info, primary_update_strategy, args.diff)
helpers.write_content_to_file(file_info, primary_update_strategy, args.diff, '', True)
else:
helpers.write_content_to_file(file_info, 'update-if-non-existent', args.diff)
helpers.write_content_to_file(file_info, 'update-if-non-existent', args.diff, '', True)


def module_genld(args):
Expand Down Expand Up @@ -734,6 +752,9 @@ def main():
common_parser.add_argument('--schemas-dir', '-sd', type=str,
help='everest framework directory containing the schema definitions (default: ../everest-framework/schemas)',
default=str(Path.cwd() / '../everest-framework/schemas'))
common_parser.add_argument('--licenses', '-lc', type=str,
help='license directory from which ev-cli will attempt to parse custom license texts (default ../licenses)',
default=str(Path.cwd() / '../licenses'))
common_parser.add_argument('--build-dir', '-bd', type=str,
help='everest build directory from which ev-cli will attempt to parse the everest framework schema definitions (default ./build)',
default=str(Path.cwd() / 'build'))
Expand Down
37 changes: 36 additions & 1 deletion ev-dev-tools/src/ev_cli/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ def is_template_newer(file_info) -> Tuple[bool, str]:
return (False, '')


def write_content_to_file(file_info, strategy, only_diff=False, reason = ''):
def write_content_to_file(file_info, strategy, only_diff=False, reason = '', check_license_header=False):
# strategy:
# update: update only if dest older or not existent
# force-update: update, even if dest newer
Expand Down Expand Up @@ -730,6 +730,23 @@ def write_content_to_file(file_info, strategy, only_diff=False, reason = ''):
if not file_dir.exists():
file_dir.mkdir(parents=True, exist_ok=True)

# check if file header is different from license header
if check_license_header:
if 'license_header' in file_info:
original_content = file_path.read_text()
if not original_content.startswith(file_info['license_header']):
# determine likely end of license header
search_terms = ['#ifndef', '#pragma once', '#include']
original_license_header = ''
for search in search_terms:
index = original_content.find(search)
if index >= 0:
original_license_header = original_content[0:index]
break
print(f'Keeping the existing licence header:\n{original_license_header}')
file_info['content'] = file_info['content'].replace(
file_info['license_header'], original_license_header.strip())

file_path.write_text(file_info['content'])


Expand All @@ -740,3 +757,21 @@ def write_content_to_file_and_check_template(file_info, strategy, only_diff=Fals
if newer:
update_strategy = 'force-update'
write_content_to_file(file_info, update_strategy, only_diff, reason)


def get_license_header(license_dirs, license_url):
url_schemas = ['http://', 'https://']
for url_schema in url_schemas:
if license_url.startswith(url_schema):
license_url = license_url.replace(url_schema, '', 1)
license_path = None
for license_dir in license_dirs:
check_license_path = license_dir / license_url
print(f'Checking if license "{check_license_path}" exists...')
if check_license_path.exists():
license_path = check_license_path

if not license_path:
return None
with open(license_path, 'r') as custom_license_file:
return custom_license_file.read().strip()
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
3 changes: 3 additions & 0 deletions ev-dev-tools/src/ev_cli/templates/helper_macros.j2
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ void publish_{{ var.name }}({% if var.json_type != 'null' %}{{ cpp_type(var) }}
// Copyright{% if year_tag %} {{ year_tag }}{% endif %} Pionix GmbH and Contributors to EVerest
{%- endmacro %}

{% macro print_license_header(license) %}
{{ license }}
{%- endmacro %}

{% macro print_template_info(version, title='DO NOT EDIT!', comment_sep='//') %}
{{ comment_sep }}
Expand Down
4 changes: 2 additions & 2 deletions ev-dev-tools/src/ev_cli/templates/interface-Impl.cpp.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% from "helper_macros.j2" import handle_cmd_signature, print_spdx_line %}
{{ print_spdx_line('Apache-2.0') }}
{% from "helper_macros.j2" import handle_cmd_signature, print_license_header %}
{{ print_license_header(info.license_header) }}

#include "{{ info.class_name}}.hpp"

Expand Down
4 changes: 2 additions & 2 deletions ev-dev-tools/src/ev_cli/templates/interface-Impl.hpp.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% from "helper_macros.j2" import handle_cmd_signature, print_template_info, insert_block, cpp_type, print_spdx_line %}
{{ print_spdx_line('Apache-2.0') }}
{% from "helper_macros.j2" import handle_cmd_signature, print_template_info, insert_block, cpp_type, print_license_header %}
{{ print_license_header(info.license_header) }}
#ifndef {{ info.hpp_guard }}
#define {{ info.hpp_guard }}

Expand Down
4 changes: 2 additions & 2 deletions ev-dev-tools/src/ev_cli/templates/module.cpp.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% from "helper_macros.j2" import print_spdx_line %}
{{ print_spdx_line('Apache-2.0') }}
{% from "helper_macros.j2" import print_license_header %}
{{ print_license_header(info.license_header) }}
#include "{{ info.module_header }}"

namespace module {
Expand Down
4 changes: 2 additions & 2 deletions ev-dev-tools/src/ev_cli/templates/module.hpp.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% from "helper_macros.j2" import print_template_info, insert_block, cpp_type, print_spdx_line %}
{{ print_spdx_line('Apache-2.0') }}
{% from "helper_macros.j2" import print_template_info, insert_block, cpp_type, print_license_header %}
{{ print_license_header(info.license_header) }}
#ifndef {{ info.hpp_guard }}
#define {{ info.hpp_guard }}

Expand Down
Loading