portacode 0.3.19.dev4__tar.gz → 0.3.19.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/PKG-INFO +1 -1
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/_version.py +2 -2
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/project_state_handlers.py +96 -66
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/restore.sh +0 -2
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/.claude/agents/communication-manager.md +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/.claude/settings.local.json +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/.gitignore +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/.gitmodules +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/LICENSE +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/MANIFEST.in +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/Makefile +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/README.md +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/backup.sh +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/docker-compose.yaml +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/README.md +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/__init__.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/__main__.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/cli.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/README.md +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/__init__.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/client.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/README.md +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/__init__.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/base.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/registry.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/session.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/tab_factory.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/multiplex.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/terminal.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/data.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/keypair.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/service.py +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode.egg-info/SOURCES.txt +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode.egg-info/requires.txt +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode.egg-info/top_level.txt +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/pyproject.toml +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/setup.cfg +0 -0
- {portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/setup.py +0 -0
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '0.3.19.
|
|
21
|
-
__version_tuple__ = version_tuple = (0, 3, 19, '
|
|
20
|
+
__version__ = version = '0.3.19.dev5'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 3, 19, 'dev5')
|
|
@@ -400,8 +400,8 @@ class GitManager:
|
|
|
400
400
|
logger.debug("Error getting Pygments lexer: %s", e)
|
|
401
401
|
return None
|
|
402
402
|
|
|
403
|
-
def _generate_html_diff(self, original_content: str, modified_content: str, file_path: str) -> Optional[str]:
|
|
404
|
-
"""Generate unified HTML diff with intra-line highlighting
|
|
403
|
+
def _generate_html_diff(self, original_content: str, modified_content: str, file_path: str) -> Optional[Dict[str, str]]:
|
|
404
|
+
"""Generate unified HTML diff with intra-line highlighting. Returns both minimal and full context versions."""
|
|
405
405
|
if not PYGMENTS_AVAILABLE:
|
|
406
406
|
logger.debug("Pygments not available for HTML diff generation")
|
|
407
407
|
return None
|
|
@@ -413,85 +413,115 @@ class GitManager:
|
|
|
413
413
|
original_lines = original_content.splitlines(keepends=True)
|
|
414
414
|
modified_lines = modified_content.splitlines(keepends=True)
|
|
415
415
|
|
|
416
|
-
# Generate
|
|
417
|
-
|
|
416
|
+
# Generate both minimal (3 lines context) and full context diffs
|
|
417
|
+
minimal_diff_lines = list(difflib.unified_diff(
|
|
418
418
|
original_lines,
|
|
419
419
|
modified_lines,
|
|
420
420
|
fromfile='a/' + os.path.basename(file_path),
|
|
421
421
|
tofile='b/' + os.path.basename(file_path),
|
|
422
|
-
lineterm=''
|
|
422
|
+
lineterm='',
|
|
423
|
+
n=3 # 3 lines of context (default)
|
|
423
424
|
))
|
|
424
425
|
|
|
425
|
-
|
|
426
|
-
|
|
426
|
+
full_diff_lines = list(difflib.unified_diff(
|
|
427
|
+
original_lines,
|
|
428
|
+
modified_lines,
|
|
429
|
+
fromfile='a/' + os.path.basename(file_path),
|
|
430
|
+
tofile='b/' + os.path.basename(file_path),
|
|
431
|
+
lineterm='',
|
|
432
|
+
n=len(original_lines) + len(modified_lines) # Show all lines
|
|
433
|
+
))
|
|
427
434
|
|
|
428
|
-
#
|
|
429
|
-
|
|
435
|
+
# Parse both diffs
|
|
436
|
+
minimal_parsed = self._parse_unified_diff_with_intraline(minimal_diff_lines, original_lines, modified_lines)
|
|
437
|
+
full_parsed = self._parse_unified_diff_with_intraline(full_diff_lines, original_lines, modified_lines)
|
|
430
438
|
|
|
431
|
-
#
|
|
432
|
-
|
|
433
|
-
|
|
439
|
+
# Generate HTML for both versions
|
|
440
|
+
minimal_html = self._generate_diff_html(minimal_parsed, file_path, 'minimal')
|
|
441
|
+
full_html = self._generate_diff_html(full_parsed, file_path, 'full')
|
|
434
442
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
443
|
+
return {
|
|
444
|
+
'minimal': minimal_html,
|
|
445
|
+
'full': full_html
|
|
446
|
+
}
|
|
438
447
|
|
|
439
|
-
|
|
440
|
-
|
|
448
|
+
except Exception as e:
|
|
449
|
+
logger.error("Error generating HTML diff: %s", e)
|
|
450
|
+
return None
|
|
451
|
+
|
|
452
|
+
def _generate_diff_html(self, parsed_diff: List[Dict], file_path: str, view_mode: str) -> str:
|
|
453
|
+
"""Generate HTML for a parsed diff."""
|
|
454
|
+
# Get Pygments lexer for syntax highlighting
|
|
455
|
+
lexer = self._get_pygments_lexer(file_path)
|
|
456
|
+
|
|
457
|
+
# Build HTML
|
|
458
|
+
html_parts = []
|
|
459
|
+
html_parts.append(f'<div class="unified-diff-container" data-view-mode="{view_mode}">')
|
|
460
|
+
|
|
461
|
+
# Add stats header with toggle
|
|
462
|
+
line_additions = sum(1 for line in parsed_diff if line['type'] == 'add')
|
|
463
|
+
line_deletions = sum(1 for line in parsed_diff if line['type'] == 'delete')
|
|
464
|
+
|
|
465
|
+
html_parts.append(f'''
|
|
466
|
+
<div class="diff-stats">
|
|
467
|
+
<div class="diff-stats-left">
|
|
441
468
|
<span class="additions">+{line_additions}</span>
|
|
442
469
|
<span class="deletions">-{line_deletions}</span>
|
|
443
470
|
<span class="file-path">{os.path.basename(file_path)}</span>
|
|
444
471
|
</div>
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
472
|
+
<div class="diff-stats-right">
|
|
473
|
+
<button class="diff-toggle-btn" data-current-mode="{view_mode}">
|
|
474
|
+
<i class="fas fa-eye"></i>
|
|
475
|
+
<span class="toggle-text">{''}</span>
|
|
476
|
+
</button>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
''')
|
|
480
|
+
|
|
481
|
+
# Generate unified diff view
|
|
482
|
+
html_parts.append('<div class="diff-content">')
|
|
483
|
+
html_parts.append('<table class="diff-table">')
|
|
484
|
+
|
|
485
|
+
for line_info in parsed_diff:
|
|
486
|
+
if line_info['type'] == 'header':
|
|
487
|
+
continue # Skip diff headers
|
|
460
488
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
489
|
+
line_type = line_info['type']
|
|
490
|
+
old_line_num = line_info.get('old_line_num', '')
|
|
491
|
+
new_line_num = line_info.get('new_line_num', '')
|
|
492
|
+
content = line_info['content']
|
|
493
|
+
intraline_html = line_info.get('intraline_html', '')
|
|
494
|
+
|
|
495
|
+
# Use intra-line highlighted content if available, otherwise apply syntax highlighting
|
|
496
|
+
if intraline_html:
|
|
497
|
+
final_content = intraline_html
|
|
498
|
+
elif lexer and content.strip():
|
|
499
|
+
try:
|
|
500
|
+
# Apply syntax highlighting to the content (without the +/- prefix)
|
|
501
|
+
clean_content = content[1:] if content and content[0] in '+-' else content
|
|
502
|
+
highlighted = highlight(clean_content, lexer, HtmlFormatter(nowrap=True, noclasses=False))
|
|
503
|
+
final_content = content[0] + highlighted if content and content[0] in '+-' else highlighted
|
|
504
|
+
except Exception:
|
|
473
505
|
final_content = self._escape_html(content)
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
row_class = f'diff-line diff-{line_type}'
|
|
477
|
-
|
|
478
|
-
html_parts.append(f'''
|
|
479
|
-
<tr class="{row_class}">
|
|
480
|
-
<td class="line-num old-line-num">{old_line_num}</td>
|
|
481
|
-
<td class="line-num new-line-num">{new_line_num}</td>
|
|
482
|
-
<td class="line-content">{final_content}</td>
|
|
483
|
-
</tr>
|
|
484
|
-
''')
|
|
485
|
-
|
|
486
|
-
html_parts.append('</table>')
|
|
487
|
-
html_parts.append('</div>')
|
|
488
|
-
html_parts.append('</div>')
|
|
506
|
+
else:
|
|
507
|
+
final_content = self._escape_html(content)
|
|
489
508
|
|
|
490
|
-
|
|
509
|
+
# CSS classes for different line types
|
|
510
|
+
row_class = f'diff-line diff-{line_type}'
|
|
491
511
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
512
|
+
html_parts.append(f'''
|
|
513
|
+
<tr class="{row_class}">
|
|
514
|
+
<td class="line-num old-line-num">{old_line_num}</td>
|
|
515
|
+
<td class="line-num new-line-num">{new_line_num}</td>
|
|
516
|
+
<td class="line-content">{final_content}</td>
|
|
517
|
+
</tr>
|
|
518
|
+
''')
|
|
519
|
+
|
|
520
|
+
html_parts.append('</table>')
|
|
521
|
+
html_parts.append('</div>')
|
|
522
|
+
html_parts.append('</div>')
|
|
523
|
+
|
|
524
|
+
return ''.join(html_parts)
|
|
495
525
|
|
|
496
526
|
def _parse_unified_diff_with_intraline(self, diff_lines, original_lines, modified_lines):
|
|
497
527
|
"""Parse unified diff and add intra-line character highlighting."""
|
|
@@ -1556,8 +1586,8 @@ class ProjectStateManager:
|
|
|
1556
1586
|
# Compute diff details for the client
|
|
1557
1587
|
diff_details = git_manager._compute_diff_details(original_content, modified_content)
|
|
1558
1588
|
|
|
1559
|
-
# Generate HTML diff with syntax highlighting
|
|
1560
|
-
|
|
1589
|
+
# Generate HTML diff with syntax highlighting (both minimal and full context)
|
|
1590
|
+
html_diff_versions = git_manager._generate_html_diff(original_content, modified_content, file_path)
|
|
1561
1591
|
|
|
1562
1592
|
# Create a descriptive title for the diff
|
|
1563
1593
|
title_parts = []
|
|
@@ -1585,7 +1615,7 @@ class ProjectStateManager:
|
|
|
1585
1615
|
'from_hash': from_hash,
|
|
1586
1616
|
'to_hash': to_hash,
|
|
1587
1617
|
'diff_timeline': True,
|
|
1588
|
-
'
|
|
1618
|
+
'html_diff_versions': html_diff_versions
|
|
1589
1619
|
})
|
|
1590
1620
|
|
|
1591
1621
|
project_state.open_tabs[tab_key] = diff_tab
|
|
@@ -8,8 +8,6 @@ BACKUP_DIR="${1:-$PWD/../backups}"
|
|
|
8
8
|
VOLUME_NAME="portacode_pgdata"
|
|
9
9
|
SERVICE="db"
|
|
10
10
|
|
|
11
|
-
SDFSD
|
|
12
|
-
|
|
13
11
|
# ─── PICK A BACKUP ────────────────────────────────────────────────────────
|
|
14
12
|
mapfile -t BACKUPS < <(
|
|
15
13
|
find "$BACKUP_DIR" -maxdepth 1 -type f -name "pgdata-*.tar.gz" \
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/file_handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/system_handlers.py
RENAMED
|
File without changes
|
{portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/tab_factory.py
RENAMED
|
File without changes
|
{portacode-0.3.19.dev4 → portacode-0.3.19.dev5}/portacode/connection/handlers/terminal_handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|