Skip to content

Phase 2: Refactor zip_working_dir to use git ls-files - #294

Open
GargiGupta-io wants to merge 2 commits into
keras-team:mainfrom
GargiGupta-io:phase-2-refactor-traversal
Open

Phase 2: Refactor zip_working_dir to use git ls-files#294
GargiGupta-io wants to merge 2 commits into
keras-team:mainfrom
GargiGupta-io:phase-2-refactor-traversal

Conversation

@GargiGupta-io

Copy link
Copy Markdown

Integrates git ls-files into zip_working_dir():

  • When in a git repo, uses git ls-files to respect .gitignore
  • Falls back to directory traversal when not in a git repo

Part of #288 (Phase 2 of 4). Merge after #293.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces Git-aware packaging in kinetic/utils/packager.py by utilizing git ls-files to package only tracked and non-ignored files, falling back to os.walk if Git is unavailable. The review feedback highlights a robustness issue where path exclusions can fail if relative and absolute paths are mixed. To resolve this, it is recommended to use os.path.abspath instead of os.path.normpath when normalizing paths in both _path_is_excluded and zip_working_dir.

Comment thread kinetic/utils/packager.py
Comment on lines +49 to +56
def _path_is_excluded(path: str, exclude_paths: set[str]) -> bool:
if not exclude_paths:
return False
normalized_path = os.path.normpath(path)
return any(
normalized_path == excluded or normalized_path.startswith(excluded + os.sep)
for excluded in exclude_paths
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Comparing relative paths with absolute paths in _path_is_excluded will cause exclusions to fail when base_dir is specified as a relative path (e.g., . or ./), while exclude_paths contains absolute paths (which is the default for resolved Data objects). Converting all paths to absolute paths using os.path.abspath ensures robust and consistent comparison.

Suggested change
def _path_is_excluded(path: str, exclude_paths: set[str]) -> bool:
if not exclude_paths:
return False
normalized_path = os.path.normpath(path)
return any(
normalized_path == excluded or normalized_path.startswith(excluded + os.sep)
for excluded in exclude_paths
)
def _path_is_excluded(path: str, exclude_paths: set[str]) -> bool:
if not exclude_paths:
return False
normalized_path = os.path.abspath(path)
return any(
normalized_path == excluded or normalized_path.startswith(excluded + os.sep)
for excluded in exclude_paths
)
References
  1. Demand Robustness: Do not accept fragile code. If the proposed code is not robust enough or lacks proper error handling, explicitly tell the author why the current approach is brittle and what must be done to reinforce it. (link)

Comment thread kinetic/utils/packager.py
Comment on lines 102 to +122
normalized_excludes = {os.path.normpath(p) for p in exclude_paths}

with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(base_dir):
# Exclude .git, __pycache__, and Data-referenced directories
dirs[:] = [
d
for d in dirs
if d not in [".git", "__pycache__"]
and os.path.normpath(os.path.join(root, d)) not in normalized_excludes
]

for file in files:
file_path = os.path.join(root, file)
if os.path.normpath(file_path) in normalized_excludes:
continue
archive_name = os.path.relpath(file_path, base_dir)
zipf.write(file_path, archive_name)
git_files = _list_git_files(base_dir)
if git_files is not None:
_write_git_files(zipf, base_dir, git_files, normalized_excludes)
else:
for root, dirs, files in os.walk(base_dir):
dirs[:] = [
d
for d in dirs
if d not in [".git", "__pycache__"]
and os.path.normpath(os.path.join(root, d)) not in normalized_excludes
]

for file in files:
file_path = os.path.join(root, file)
if os.path.normpath(file_path) in normalized_excludes:
continue
archive_name = os.path.relpath(file_path, base_dir)
zipf.write(file_path, archive_name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

To ensure that path exclusions work reliably regardless of whether base_dir is specified as a relative or absolute path, we should normalize all excluded paths to absolute paths using os.path.abspath instead of os.path.normpath.

  normalized_excludes = {os.path.abspath(p) for p in exclude_paths}

  with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zipf:
    git_files = _list_git_files(base_dir)
    if git_files is not None:
      _write_git_files(zipf, base_dir, git_files, normalized_excludes)
    else:
      for root, dirs, files in os.walk(base_dir):
        dirs[:] = [
          d
          for d in dirs
          if d not in [".git", "__pycache__"]
          and os.path.abspath(os.path.join(root, d)) not in normalized_excludes
        ]

        for file in files:
          file_path = os.path.join(root, file)
          if os.path.abspath(file_path) in normalized_excludes:
            continue
          archive_name = os.path.relpath(file_path, base_dir)
          zipf.write(file_path, archive_name)
References
  1. Poke Holes in the Implementation: Your goal is to critically test the logic. Actively search for and point out failing edge cases, race conditions, or unhandled exceptions in the implementation. (link)

Adds helper functions to support git-aware packaging:
- _list_git_files(): Lists tracked and non-ignored untracked files
- _path_is_excluded(): Checks if a path should be excluded
- _write_git_files(): Recursively writes files to ZIP respecting exclusions

These functions enable respecting .gitignore when zipping working directories.
- Uses git ls-files when in a git repository to respect .gitignore
- Falls back to directory traversal with os.walk when not in a git repo
- Maintains all existing features: empty directory preservation, secret detection, path exclusion
- Updated docstring to document git integration
@GargiGupta-io
GargiGupta-io force-pushed the phase-2-refactor-traversal branch from 4ffb14b to d1f1dda Compare August 11, 2026 19:42
@GargiGupta-io

Copy link
Copy Markdown
Author

Merge order note: These 4 phases should be merged in sequence:

  1. Phase 1 (in branch phase-1-git-integration) - Add git ls-files helper functions
  2. Phase 2 (this PR Phase 2: Refactor zip_working_dir to use git ls-files #294) - Integrate with zip_working_dir
  3. Phase 3 (PR Phase 3: Add comprehensive tests for gitignore functionality #295) - Add tests
  4. Phase 4 (PR Phase 4: Enable git-aware packaging by default #296) - Documentation

All code is ready and tested. Phases 1-3 have been pushed and are ready to merge.

@GargiGupta-io

Copy link
Copy Markdown
Author

Implementation Note: 4-Phase Git Integration

This is Phase 2 of 4 for adding git-aware packaging with .gitignore support.

Merge Order Required:

  1. Phase 1 - Available in branch phase-1-git-integration

    • Adds: _list_git_files(), _path_is_excluded(), _write_git_files() helper functions
  2. Phase 2 - This PR (Phase 2: Refactor zip_working_dir to use git ls-files #294)

    • Integrates git ls-files into zip_working_dir()
  3. Phase 3 - PR Phase 3: Add comprehensive tests for gitignore functionality #295

    • Adds comprehensive tests
  4. Phase 4 - PR Phase 4: Enable git-aware packaging by default #296

    • Documentation updates

Status:

✅ All code is complete and tested
✅ All branches merge cleanly in sequence
✅ Phase 1 branch is ready to pull/merge

How to Proceed:

Either:

All phases tested locally and verified to merge without conflicts when applied in order.

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.

1 participant