sistemato la schermata per la differenza dei file
This commit is contained in:
parent
7e0435ab7d
commit
df6ebec3e2
BIN
PyUcc.ico
BIN
PyUcc.ico
Binary file not shown.
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 32 KiB |
74
pyucc/_version.py
Normal file
74
pyucc/_version.py
Normal file
@ -0,0 +1,74 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# File generated by PyInstaller GUI Wrapper. DO NOT EDIT MANUALLY.
|
||||
# Contains build-time information scraped from Git (if available)
|
||||
# and a helper function to format version strings.
|
||||
|
||||
import re
|
||||
|
||||
# --- Version Data (Generated) ---
|
||||
__version__ = "v.0.0.0.11-0-g7e0435a-dirty"
|
||||
GIT_COMMIT_HASH = "7e0435ab7d0316bd2bcf5fdcd33cb84c39efa09c"
|
||||
GIT_BRANCH = "master"
|
||||
BUILD_TIMESTAMP = "2025-11-27T12:49:18.815605+00:00"
|
||||
IS_GIT_REPO = True
|
||||
|
||||
# --- Default Values (for comparison or fallback) ---
|
||||
DEFAULT_VERSION = "0.0.0+unknown"
|
||||
DEFAULT_COMMIT = "Unknown"
|
||||
DEFAULT_BRANCH = "Unknown"
|
||||
|
||||
# --- Helper Function ---
|
||||
def get_version_string(format_string=None):
|
||||
"""
|
||||
Returns a formatted string based on the build version information.
|
||||
|
||||
Args:
|
||||
format_string (str, optional): A format string using placeholders.
|
||||
Defaults to "{version} ({branch}/{commit_short})" if None.
|
||||
Placeholders:
|
||||
{{version}}: Full version string (e.g., 'v1.0.0-5-gabcdef-dirty')
|
||||
{{tag}}: Clean tag part if exists (e.g., 'v1.0.0'), else DEFAULT_VERSION.
|
||||
{{commit}}: Full Git commit hash.
|
||||
{{commit_short}}: Short Git commit hash (7 chars).
|
||||
{{branch}}: Git branch name.
|
||||
{{dirty}}: '-dirty' if the repo was dirty, empty otherwise.
|
||||
{{timestamp}}: Full build timestamp (ISO 8601 UTC).
|
||||
{{timestamp_short}}: Build date only (YYYY-MM-DD).
|
||||
{{is_git}}: 'Git' if IS_GIT_REPO is True, 'Unknown' otherwise.
|
||||
|
||||
Returns:
|
||||
str: The formatted version string, or an error message if formatting fails.
|
||||
"""
|
||||
if format_string is None:
|
||||
format_string = "{version} ({branch}/{commit_short})" # Default format
|
||||
|
||||
replacements = {}
|
||||
try:
|
||||
replacements['version'] = __version__ if __version__ else DEFAULT_VERSION
|
||||
replacements['commit'] = GIT_COMMIT_HASH if GIT_COMMIT_HASH else DEFAULT_COMMIT
|
||||
replacements['commit_short'] = GIT_COMMIT_HASH[:7] if GIT_COMMIT_HASH and len(GIT_COMMIT_HASH) >= 7 else DEFAULT_COMMIT
|
||||
replacements['branch'] = GIT_BRANCH if GIT_BRANCH else DEFAULT_BRANCH
|
||||
replacements['timestamp'] = BUILD_TIMESTAMP if BUILD_TIMESTAMP else "Unknown"
|
||||
replacements['timestamp_short'] = BUILD_TIMESTAMP.split('T')[0] if BUILD_TIMESTAMP and 'T' in BUILD_TIMESTAMP else "Unknown"
|
||||
replacements['is_git'] = "Git" if IS_GIT_REPO else "Unknown"
|
||||
replacements['dirty'] = "-dirty" if __version__ and __version__.endswith('-dirty') else ""
|
||||
|
||||
tag = DEFAULT_VERSION
|
||||
if __version__ and IS_GIT_REPO:
|
||||
match = re.match(r'^(v?([0-9]+(?:\.[0-9]+)*))', __version__)
|
||||
if match:
|
||||
tag = match.group(1)
|
||||
replacements['tag'] = tag
|
||||
|
||||
output_string = format_string
|
||||
for placeholder, value in replacements.items():
|
||||
pattern = re.compile(r'{{\s*' + re.escape(placeholder) + r'\s*}}')
|
||||
output_string = pattern.sub(str(value), output_string)
|
||||
|
||||
if re.search(r'{\s*\w+\s*}', output_string):
|
||||
pass # Or log a warning: print(f"Warning: Unreplaced placeholders found: {output_string}")
|
||||
|
||||
return output_string
|
||||
|
||||
except Exception as e:
|
||||
return f"[Formatting Error: {e}]"
|
||||
@ -144,9 +144,6 @@ class BaselineManager:
|
||||
if compute_sha1: # also compute for 0-byte files
|
||||
try:
|
||||
sha1 = _sha1_of_file(Path(fpath))
|
||||
# Log empty __init__.py files
|
||||
if st.st_size == 0 and "__init__.py" in fn:
|
||||
print(f"[BASELINE-SCAN] {rel_unix} (size={st.st_size}) SHA1={sha1}")
|
||||
except Exception:
|
||||
sha1 = None
|
||||
files_meta.append(FileMeta(path=rel_unix, size=st.st_size, mtime=st.st_mtime, sha1=sha1))
|
||||
@ -209,16 +206,6 @@ class BaselineManager:
|
||||
os.makedirs(dst_parent, exist_ok=True)
|
||||
try:
|
||||
shutil.copy2(src_file, dst_file) # copy2 preserves metadata
|
||||
# Verify copy for empty __init__.py files
|
||||
if fm.size == 0 and "__init__.py" in fm.path:
|
||||
sha1_src = _sha1_of_file(Path(src_file))
|
||||
sha1_dst = _sha1_of_file(Path(dst_file))
|
||||
print(f"[BASELINE-COPY] {fm.path}")
|
||||
print(f" Source SHA1: {sha1_src}")
|
||||
print(f" Dest SHA1: {sha1_dst}")
|
||||
print(f" Saved SHA1: {fm.sha1}")
|
||||
if sha1_src != fm.sha1:
|
||||
print(f" WARNING: Source file changed after initial scan!")
|
||||
except Exception:
|
||||
pass # skip files that cannot be copied
|
||||
|
||||
@ -468,9 +455,6 @@ class Differ:
|
||||
# Compute SHA1 for all files, including 0-byte files
|
||||
try:
|
||||
sha1 = _sha1_of_file(Path(fpath))
|
||||
# Log empty __init__.py files
|
||||
if st.st_size == 0 and "__init__.py" in fn:
|
||||
print(f"[DIFFER-CURRENT] {rel.replace(chr(92), '/')} (size={st.st_size}) SHA1={sha1}")
|
||||
except Exception:
|
||||
sha1 = None
|
||||
files_meta.append(FileMeta(path=rel.replace("\\", "/"), size=st.st_size, mtime=st.st_mtime, sha1=sha1))
|
||||
@ -715,15 +699,6 @@ class Differ:
|
||||
return res
|
||||
|
||||
def diff(self) -> Dict:
|
||||
import sys
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
print(f"\n{'='*80}", flush=True)
|
||||
print(f"[DIFFER-START] Using baseline: {self.baseline.baseline_id}", flush=True)
|
||||
print(f"[DIFFER-START] Baseline files dir: {self.baseline_files_dir}", flush=True)
|
||||
print(f"[DIFFER-START] Current dir: {self.current_dir}", flush=True)
|
||||
print(f"{'='*80}\n", flush=True)
|
||||
|
||||
baseline_files = self.baseline.files
|
||||
current_files = self.build_current_file_list()
|
||||
pairs = self.match_files(baseline_files, current_files)
|
||||
@ -742,23 +717,6 @@ class Differ:
|
||||
for a, b in pairs:
|
||||
fa = os.path.join(self.baseline_files_dir, a.path) if a is not None else None
|
||||
fb = os.path.join(self.current_dir, b.path) if b is not None else None
|
||||
|
||||
# DEBUG: Log empty __init__.py comparisons
|
||||
if a and b and a.size == 0 and "__init__.py" in a.path:
|
||||
import sys
|
||||
print(f"\n[DIFFER-COMPARE] {a.path}", flush=True)
|
||||
print(f" Baseline SHA1 (metadata): {a.sha1}", flush=True)
|
||||
print(f" Current SHA1 (metadata): {b.sha1}", flush=True)
|
||||
print(f" Baseline file: {fa}", flush=True)
|
||||
print(f" Current file: {fb}", flush=True)
|
||||
if fa and os.path.exists(fa):
|
||||
sha1_baseline_actual = _sha1_of_file(Path(fa))
|
||||
print(f" Baseline SHA1 (actual): {sha1_baseline_actual}", flush=True)
|
||||
if fb and os.path.exists(fb):
|
||||
sha1_current_actual = _sha1_of_file(Path(fb))
|
||||
print(f" Current SHA1 (actual): {sha1_current_actual}", flush=True)
|
||||
sys.stdout.flush()
|
||||
|
||||
futures.append(ex.submit(self._diff_file_pair, fa, fb))
|
||||
for (a, b), fut in zip(pairs, futures):
|
||||
res = fut.result()
|
||||
|
||||
@ -340,20 +340,20 @@ class ActionHandlers:
|
||||
rows = (_row_from_pair(p) for p in result.get('pairs', []))
|
||||
export_rows_to_csv(csv_path, headers, rows)
|
||||
|
||||
# Generate text report
|
||||
profile_config = {
|
||||
'name': profile_name,
|
||||
'root': project,
|
||||
'paths': paths if paths else [project],
|
||||
'languages': allowed_exts if allowed_exts else [],
|
||||
'exclude_patterns': ignore_patterns
|
||||
}
|
||||
generate_differ_report(result, profile_config, baseline_id, report_path)
|
||||
except Exception:
|
||||
# non-fatal: continue even if export fails
|
||||
pass
|
||||
|
||||
# Show summary dialog
|
||||
# Generate text report
|
||||
profile_config = {
|
||||
'name': profile_name,
|
||||
'root': project,
|
||||
'paths': paths if paths else [project],
|
||||
'languages': allowed_exts if allowed_exts else [],
|
||||
'exclude_patterns': ignore_patterns
|
||||
}
|
||||
generate_differ_report(result, profile_config, baseline_id, report_path)
|
||||
self.app.log(f"Differ report saved to: {report_path}", level='INFO')
|
||||
except Exception as e:
|
||||
# non-fatal: continue even if export fails
|
||||
self.app.log(f"Failed to export differ results: {e}", level='WARNING')
|
||||
pass # Show summary dialog
|
||||
self._show_differ_summary_dialog(result, baseline_id, bdir)
|
||||
except Exception:
|
||||
self.app._set_phase('Idle')
|
||||
@ -515,25 +515,11 @@ class ActionHandlers:
|
||||
b.sha1 = None
|
||||
|
||||
# Compare hashes
|
||||
# DEBUG: Log SHA1 comparison for empty __init__.py files
|
||||
if a and b and a.size == 0 and "__init__.py" in str(a.path):
|
||||
import sys
|
||||
print(f"\n[ACTION_HANDLERS] SHA1 comparison for {a.path}", flush=True)
|
||||
print(f" a.sha1={getattr(a, 'sha1', 'NO ATTR')}", flush=True)
|
||||
print(f" b.sha1={getattr(b, 'sha1', 'NO ATTR')}", flush=True)
|
||||
print(f" hasattr(a, 'sha1')={hasattr(a, 'sha1')}", flush=True)
|
||||
print(f" a.sha1 is truthy={bool(a.sha1) if hasattr(a, 'sha1') else False}", flush=True)
|
||||
print(f" b.sha1 is truthy={bool(b.sha1)}", flush=True)
|
||||
print(f" Match: {a.sha1 == b.sha1 if (hasattr(a, 'sha1') and a.sha1 and b.sha1) else 'N/A'}", flush=True)
|
||||
sys.stdout.flush()
|
||||
|
||||
if hasattr(a, 'sha1') and a.sha1 and b.sha1 and a.sha1 == b.sha1:
|
||||
# Identical files
|
||||
res['counts'] = {'added': 0, 'deleted': 0, 'modified': 0, 'unmodified': 1}
|
||||
else:
|
||||
# Modified file
|
||||
if a and b and a.size == 0 and "__init__.py" in str(a.path):
|
||||
print(f" → Marked as MODIFIED!", flush=True)
|
||||
res['counts'] = {'added': 0, 'deleted': 0, 'modified': 1, 'unmodified': 0}
|
||||
else:
|
||||
# Both None (shouldn't happen)
|
||||
|
||||
@ -114,6 +114,9 @@ class DiffViewer(tk.Toplevel):
|
||||
highlightbackground='#ccc')
|
||||
self.minimap.grid(row=1, column=1, sticky='nsew', padx=2, pady=0)
|
||||
|
||||
# Ridisegna minimap quando il canvas viene ridimensionato
|
||||
self.minimap.bind('<Configure>', lambda e: self._draw_minimap())
|
||||
|
||||
# Scrollbar orizzontali
|
||||
scrollbar_h_a = ttk.Scrollbar(main_frame, orient='horizontal', command=self.text_a.xview)
|
||||
scrollbar_h_a.grid(row=2, column=0, sticky='ew', padx=(2, 1))
|
||||
@ -413,13 +416,22 @@ class DiffViewer(tk.Toplevel):
|
||||
# Rimuovi rettangolo precedente
|
||||
self.minimap.delete('viewport')
|
||||
|
||||
# Calcola posizione viewport
|
||||
if not hasattr(self, 'minimap_blocks') or not self.minimap_blocks:
|
||||
return
|
||||
|
||||
# Calcola posizione viewport basandosi sul totale delle linee
|
||||
yview = self.text_a.yview()
|
||||
canvas_height = self.minimap.winfo_height()
|
||||
canvas_width = self.minimap.winfo_width()
|
||||
|
||||
# yview restituisce (frazione_inizio, frazione_fine) del documento
|
||||
# Usa queste frazioni direttamente sull'altezza del canvas
|
||||
y1 = yview[0] * canvas_height
|
||||
y2 = yview[1] * canvas_height
|
||||
canvas_width = self.minimap.winfo_width()
|
||||
|
||||
# Assicurati che il viewport sia visibile (minimo 5 pixel)
|
||||
if y2 - y1 < 5:
|
||||
y2 = y1 + 5
|
||||
|
||||
# Disegna rettangolo viewport
|
||||
self.minimap.create_rectangle(0, y1, canvas_width, y2,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user