mirror of
https://github.com/fosrl/pangolin.git
synced 2026-04-15 22:36:37 +00:00
137 lines
4.8 KiB
Python
137 lines
4.8 KiB
Python
import os
|
|
import sys
|
|
|
|
# --- Configuration ---
|
|
# The header text to be added to the files.
|
|
HEADER_TEXT = """/*
|
|
* This file is part of a proprietary work.
|
|
*
|
|
* Copyright (c) 2025-2026 Fossorial, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This file is licensed under the Fossorial Commercial License.
|
|
* You may not use this file except in compliance with the License.
|
|
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
|
|
*
|
|
* This file is not licensed under the AGPLv3.
|
|
*/
|
|
"""
|
|
|
|
HEADER_NORMALIZED = HEADER_TEXT.strip()
|
|
|
|
|
|
def extract_leading_block_comment(content):
|
|
"""
|
|
If the file content begins with a /* ... */ block comment, return the
|
|
full text of that comment (including the delimiters) and the index at
|
|
which the rest of the file starts (after any trailing newlines).
|
|
Returns (None, 0) when no such comment is found.
|
|
"""
|
|
stripped = content.lstrip()
|
|
if not stripped.startswith('/*'):
|
|
return None, 0
|
|
|
|
# Account for any leading whitespace before the comment
|
|
comment_start = content.index('/*')
|
|
end_marker = content.find('*/', comment_start + 2)
|
|
if end_marker == -1:
|
|
return None, 0
|
|
|
|
comment_end = end_marker + 2 # position just after '*/'
|
|
comment_text = content[comment_start:comment_end].strip()
|
|
|
|
# Advance past any whitespace / newlines that follow the closing */
|
|
rest_start = comment_end
|
|
while rest_start < len(content) and content[rest_start] in '\n\r':
|
|
rest_start += 1
|
|
|
|
return comment_text, rest_start
|
|
|
|
|
|
def should_add_header(file_path):
|
|
"""
|
|
Checks if a file should receive the commercial license header.
|
|
Returns True if 'server/private' is in the path.
|
|
"""
|
|
if 'server/private' in file_path.lower():
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def process_directory(root_dir):
|
|
"""
|
|
Recursively scans a directory and adds/replaces/removes headers in
|
|
qualifying .ts or .tsx files, skipping any 'node_modules' directories.
|
|
"""
|
|
print(f"Scanning directory: {root_dir}")
|
|
files_processed = 0
|
|
files_modified = 0
|
|
|
|
for root, dirs, files in os.walk(root_dir):
|
|
# Exclude 'node_modules' directories from the scan.
|
|
if 'node_modules' in dirs:
|
|
dirs.remove('node_modules')
|
|
|
|
for file in files:
|
|
if not (file.endswith('.ts') or file.endswith('.tsx')):
|
|
continue
|
|
|
|
file_path = os.path.join(root, file)
|
|
files_processed += 1
|
|
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
original_content = f.read()
|
|
|
|
existing_comment, body_start = extract_leading_block_comment(
|
|
original_content
|
|
)
|
|
has_any_header = existing_comment is not None
|
|
has_correct_header = existing_comment == HEADER_NORMALIZED
|
|
|
|
body = original_content[body_start:] if has_any_header else original_content
|
|
|
|
if should_add_header(file_path):
|
|
if has_correct_header:
|
|
print(f"Header up-to-date: {file_path}")
|
|
else:
|
|
# Either no header exists or the header is outdated — write
|
|
# the correct one.
|
|
action = "Replaced header in" if has_any_header else "Added header to"
|
|
new_content = HEADER_NORMALIZED + '\n\n' + body
|
|
with open(file_path, 'w', encoding='utf-8') as f:
|
|
f.write(new_content)
|
|
print(f"{action}: {file_path}")
|
|
files_modified += 1
|
|
else:
|
|
if has_any_header:
|
|
# Remove the header — it shouldn't be here.
|
|
with open(file_path, 'w', encoding='utf-8') as f:
|
|
f.write(body)
|
|
print(f"Removed header from: {file_path}")
|
|
files_modified += 1
|
|
else:
|
|
print(f"No header needed: {file_path}")
|
|
|
|
except Exception as e:
|
|
print(f"Error processing file {file_path}: {e}")
|
|
|
|
print("\n--- Scan Complete ---")
|
|
print(f"Total .ts or .tsx files found: {files_processed}")
|
|
print(f"Files modified (added/replaced/removed): {files_modified}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Get the target directory from the command line arguments.
|
|
# If no directory is provided, it uses the current directory ('.').
|
|
if len(sys.argv) > 1:
|
|
target_directory = sys.argv[1]
|
|
else:
|
|
target_directory = '.' # Default to current directory
|
|
|
|
if not os.path.isdir(target_directory):
|
|
print(f"Error: Directory '{target_directory}' not found.")
|
|
sys.exit(1)
|
|
|
|
process_directory(os.path.abspath(target_directory)) |