Skip to content

Conversation

@zghp
Copy link
Contributor

@zghp zghp commented Jan 9, 2026

No description provided.

@zghp zghp requested a review from TB-1993 January 9, 2026 11:27
@zghp zghp self-assigned this Jan 9, 2026
@zghp zghp requested a review from a team as a code owner January 9, 2026 11:27
Copilot AI review requested due to automatic review settings January 9, 2026 11:27
@github-actions
Copy link

github-actions bot commented Jan 9, 2026


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


1 out of 2 committers have signed the CLA.
✅ (TB-1993)[https://github.com/TB-1993]
@zghp
zghp seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@rdkcmf-jenkins
Copy link
Contributor

b'## Blackduck scan failure details

Summary: 0 violations, 0 files pending approval, 1 file pending identification.

  • Protex Server Path: /home/blackduck/github/xts_core/52/rdkcentral/xts_core

  • Commit: 9db6372

Report detail: gist'

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR significantly refactors the XTS alias management system to support multiple input types (URLs, files, and directories) with improved caching and a cleaner CLI interface.

Key changes:

  • Rewrote alias management to handle URLs, single files, and directories of .xts files
  • Changed CLI from xts alias subcommands to xts --alias flag-based interface
  • Simplified the main XTS class by removing auto-discovery of .xts files in favor of explicit alias resolution
  • Introduced hash-based cache naming to avoid file collisions

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 10 comments.

File Description
src/xts_core/xts_alias.py Complete rewrite with new helper functions, improved caching logic, directory support, and CLI handler
src/xts_core/xts.py Removed old alias subcommand parsing, removed auto-discovery, simplified to use alias-only workflow with new help system

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 36 to +129
ensure_dirs()
filename = hashlib.sha256(url.encode()).hexdigest() + ".xts"
path = os.path.join(CACHE_DIR, filename)

if not os.path.exists(path):
print(f"Fetching remote .xts config from: {url}")
r = requests.get(url)
r.raise_for_status()
with open(path, "w", encoding="utf-8") as f:
f.write(r.text)
# filename = hashlib.sha256(url.encode()).hexdigest() + ".xts"
filename = Path(urlparse(url).path).name
if not filename:
raise ValueError(f"URL does not contain a filename: {url}")

cached_path = os.path.join(CACHE_DIR, filename)

print(f"Fetching remote .xts config from: {url}")
r = requests.get(url)
r.raise_for_status()

with open(cached_path, "w", encoding="utf-8") as f:
f.write(r.text)

return path
return cached_path
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fetch_url_to_cache function now always re-downloads the file even if it already exists in cache (the if not os.path.exists(path) check was removed). This could lead to unnecessary network requests and slower performance. Consider adding back a check to skip downloading if the file already exists, or add a force parameter to control this behavior.

Copilot uses AI. Check for mistakes.

def _cache_name_for_local_file(src: Path) -> str:
"""
Produce a stable cache filename for a local file, avoiding collisoins
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "collisoins" should be "collisions".

Suggested change
Produce a stable cache filename for a local file, avoiding collisoins
Produce a stable cache filename for a local file, avoiding collisions

Copilot uses AI. Check for mistakes.
cache_name = _cache_name_for_local_file(src)
dst = Path(CACHE_DIR) / cache_name

shutil.copy2(src, dst) #ovewrite to refresh
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "#ovewrite" should be "# overwrite" (missing space after #).

Suggested change
shutil.copy2(src, dst) #ovewrite to refresh
shutil.copy2(src, dst) # overwrite to refresh

Copilot uses AI. Check for mistakes.
Comment on lines 338 to 344
if remove_name is not None:
removed = remove_alias(remove_name)
if removed:
print(f"Removed alias: {remove_name}")
return 0
print(f"Alias not found: {remove_name}")
return 2
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable 'removed' is assigned the return value of remove_alias(), but remove_alias() returns None. This check will always fail. The logic should be revised to check whether the alias exists before attempting removal, or the remove_alias function should return a boolean.

Copilot uses AI. Check for mistakes.
Comment on lines 191 to 198
def remove_alias(name: str) -> None:
"""
Remove an alias if it exists.
"""
aliases = load_aliases()
if name in aliases:
del aliases[name]
with open(ALIAS_FILE, "w") as f:
json.dump(aliases, f, indent=2)
save_aliases(aliases)
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The remove_alias function returns None in all cases, but the calling code checks if the return value is truthy (line 340). This will always evaluate to False, making the success message unreachable. The function should return True when an alias is removed or False when it doesn't exist.

Copilot uses AI. Check for mistakes.
if not resolved_xts_path:
error(f"Alias '{alias_name}' not found. Add it via: xts --alias <path|url|dir> [--name <name>]")

# laod xts config remove alias name from argv before parsing
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "laod" should be "load".

Suggested change
# laod xts config remove alias name from argv before parsing
# load xts config remove alias name from argv before parsing

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings January 14, 2026 11:44
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

from xts_core import utils

try:
from .xts_arg_parser import XTSArgumentParser
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space between 'from' and '.xts_arg_parser'. Should be 'from .xts_arg_parser import XTSArgumentParser'.

Suggested change
from .xts_arg_parser import XTSArgumentParser
from .xts_arg_parser import XTSArgumentParser

Copilot uses AI. Check for mistakes.

def _cache_name_for_local_file(src: Path) -> str:
"""
Produce a stable cache filename for a local file, avoiding collisoins
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'collisoins' to 'collisions'.

Suggested change
Produce a stable cache filename for a local file, avoiding collisoins
Produce a stable cache filename for a local file, avoiding collisions

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings January 19, 2026 11:46
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 20 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

os.makedirs(CACHE_DIR, exist_ok=True)
os.makedirs(os.path.dirname(ALIAS_FILE), exist_ok=True)

# move these to utils
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 60 "move these to utils" suggests these helper functions should be relocated. If the intention is to move _is_url to the existing utils.is_url function, this creates duplication. The existing utils.is_url uses a simpler string startswith check, while _is_url uses urlparse with more robust validation. Consider consolidating these into a single implementation in utils.py or removing the comment if the functions should remain here.

Suggested change
# move these to utils
# Local helper functions; _is_url intentionally differs from utils.is_url
# (uses urllib.parse.urlparse for stricter URL validation).

Copilot uses AI. Check for mistakes.
action='store',
default=None,
help='URI of xts file to add alias of',
nargs=argparse.OPTIONAL)
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nargs=argparse.OPTIONAL should be nargs='?' for an optional positional argument in argparse. argparse.OPTIONAL is not a valid constant; the correct value is the string '?'.

Suggested change
nargs=argparse.OPTIONAL)
nargs='?')

Copilot uses AI. Check for mistakes.
cache_name = _cache_name_for_local_file(src)
dst = Path(CACHE_DIR) / cache_name

shutil.copy2(src, dst) #overwrite to refresh
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inline comment shows lack of proper spacing around the '#' character. According to PEP 8, there should be at least two spaces before an inline comment and one space between the '#' and the comment text. The comment should be: '# overwrite to refresh'

Suggested change
shutil.copy2(src, dst) #overwrite to refresh
shutil.copy2(src, dst) # overwrite to refresh

Copilot uses AI. Check for mistakes.
return True
return False

def resolve_alias_to_xts_path(alias_name: str) -> str | None:
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type annotation 'str | None' uses the Python 3.10+ union syntax. If the project needs to support Python 3.9 or earlier, this should use 'Optional[str]' from the typing module instead. Check the project's Python version requirements to ensure compatibility.

Copilot uses AI. Check for mistakes.
remaining_args.append(args.alias)
xts_alias.run_alias_builtin(remaining_args)
raise SystemExit(0)
resolved_xts_path = xts_alias.resolve_alias_to_xts_path(args.alias)
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resolved_xts_path may be None if the alias is not found in resolve_alias_to_xts_path. Setting self.xts_config to None will cause an error in the xts_config setter at line 130 ("xts config specified does not exist"). Consider adding explicit validation and providing a more helpful error message to the user about the unknown alias.

Suggested change
resolved_xts_path = xts_alias.resolve_alias_to_xts_path(args.alias)
resolved_xts_path = xts_alias.resolve_alias_to_xts_path(args.alias)
if resolved_xts_path is None:
# Provide a clear error when the alias cannot be resolved instead of
# passing None into the xts_config setter.
error(
f'Unknown alias "{args.alias}". '
'Use "xts --alias list" to see available aliases.'
)
raise SystemExit(1)

Copilot uses AI. Check for mistakes.
cache_name = _cache_name_for_local_file(src)
dst = Path(CACHE_DIR) / cache_name

shutil.copy2(src, dst) #overwrite to refresh
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment indicates 'overwrite to refresh', but shutil.copy2 preserves file metadata including modification times from the source. If the intention is to always refresh with the latest source content, this is correct. However, if modification times are important for cache invalidation logic, consider documenting this behavior more explicitly or using shutil.copy instead.

Suggested change
shutil.copy2(src, dst) #overwrite to refresh
shutil.copy(src, dst) # overwrite to refresh cache content and metadata

Copilot uses AI. Check for mistakes.
filename = Path(urlparse(url).path).name
if not filename:
raise ValueError(f"URL does not contain a filename: {url}")

Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commented-out line suggests the previous implementation used a SHA-256 hash of the URL as the filename. The new implementation uses the actual filename from the URL path. This change creates a potential security issue: filenames from URLs could contain path traversal characters (e.g., "../evil.xts") or other problematic characters. Consider sanitizing the filename or validating that it doesn't contain directory separators before using it.

Suggested change
# Validate that the derived filename cannot be used for path traversal.
if filename in (".", ".."):
raise ValueError(f"URL contains an invalid filename: {url}")
for sep in (os.sep, os.path.altsep):
if sep and sep in filename:
raise ValueError(f"URL contains an invalid filename: {url}")

Copilot uses AI. Check for mistakes.
sys.exit(sorted(exit_code)[-1])
except Exception as e:
error(
'An unrecognised command caused an error\n\n'
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message uses 'An unrecognised command' but the word is misspelled. It should be 'An unrecognized command' (American) or 'An unrecognised command' (British). The codebase appears to use American spelling based on other comments, so 'unrecognized' is preferred.

Copilot uses AI. Check for mistakes.
Comment on lines +169 to +175
def _parse_first_arg(self):
"""
Parse CLI arguments and set up argparse for all commands.
The first argument must be either:
- a built-in option starting with '--' (currently supported: --alias)
- an alias name (resolved via ~/.xts/aliases.json to an .xts file path)
Direct .xts file usage from cwd or as the first argument is not supported.
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring states "Direct .xts file usage from cwd or as the first argument is not supported." This is a breaking change from the previous behavior where users could run 'xts file.xts command'. This should be documented in the module docstring or changelog, and error messages should clearly guide users to use aliases instead.

Copilot uses AI. Check for mistakes.
Comment on lines 40 to +45
except:
from xts_core import utils

try:
from .xts_arg_parser import XTSArgumentParser
except:
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except block directly handles BaseException.

Suggested change
except:
from xts_core import utils
try:
from .xts_arg_parser import XTSArgumentParser
except:
except ImportError:
from xts_core import utils
try:
from .xts_arg_parser import XTSArgumentParser
except ImportError:

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants