@@ -296,6 +296,149 @@ def write_shell_scripts(
296296 log (f" [b]PowerShell:[/] [yellow]. { tools_dir2 } /shell/powershell.ps1[/]" , "info" , "👉" )
297297
298298
299+ def write_lfs_skip_smudge_script (
300+ tools_dir : Path ,
301+ platforms : dict [str , list [str ]],
302+ ) -> None :
303+ """Generate a Git LFS skip-smudge script for non-current architectures.
304+
305+ This script configures Git LFS to skip downloading (smudging) binary files
306+ for architectures that are not the current system's architecture, saving
307+ bandwidth and storage space.
308+
309+ Args:
310+ tools_dir: The base directory where tools are installed
311+ platforms: Dictionary mapping platform names to list of architectures
312+
313+ """
314+ script_path = tools_dir / "configure-lfs-skip-smudge.sh"
315+
316+ script_content = textwrap .dedent ("""\
317+ #!/usr/bin/env bash
318+ # Configure Git LFS to skip downloading files for non-current architectures
319+ # Generated by dotbins
320+
321+ set -e
322+
323+ # Detect current OS and architecture
324+ OS=$(uname -s | tr '[:upper:]' '[:lower:]')
325+ [[ "$OS" == "darwin" ]] && OS="macos"
326+
327+ ARCH=$(uname -m)
328+ [[ "$ARCH" == "x86_64" ]] && ARCH="amd64"
329+ [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]] && ARCH="arm64"
330+
331+ CURRENT_PLATFORM="$OS/$ARCH"
332+
333+ echo "Detected platform: $CURRENT_PLATFORM"
334+ echo ""
335+ echo "This script will configure Git LFS to skip downloading files for other platforms."
336+ echo "You only need to run this once after cloning the repository."
337+ echo ""
338+
339+ # Create include patterns for current platform
340+ include_patterns="$CURRENT_PLATFORM/bin/**"
341+
342+ # Create exclude patterns for all other platforms
343+ exclude_patterns=""
344+ """ )
345+
346+ # Add exclude patterns for each platform/arch combination
347+ for platform , architectures in platforms .items ():
348+ for arch in architectures :
349+ script_content += f"""
350+ if [[ "$OS" != "{ platform } " ]] || [[ "$ARCH" != "{ arch } " ]]; then
351+ exclude_patterns="${{exclude_patterns}} { platform } /{ arch } /bin/**"
352+ fi"""
353+
354+ script_content += """
355+
356+ echo "Setting up Git LFS skip-smudge for non-current platforms..."
357+
358+ # Configure Git to skip smudge for specific paths
359+ # This prevents automatic downloading of LFS files during checkout
360+ for pattern in $exclude_patterns; do
361+ echo " Configuring skip for: $pattern"
362+ # Set skip-smudge for specific paths
363+ git config --local --add lfs.fetchexclude "$pattern"
364+ done
365+
366+ echo ""
367+ echo "✅ LFS skip-smudge configuration complete!"
368+ echo ""
369+ echo "Files for your current platform ($CURRENT_PLATFORM) will be downloaded automatically."
370+ echo "Other platforms will be skipped to save bandwidth and disk space."
371+ echo ""
372+ echo "Useful commands:"
373+ echo " Download current platform files: git lfs pull"
374+ echo " Download a specific platform: git lfs pull --include=\\ "linux/amd64/bin/**\\ ""
375+ echo " Download ALL platforms: git lfs pull --include=\\ "*\\ ""
376+ echo " Check LFS file status: git lfs ls-files"
377+ echo ""
378+ echo "To reset this configuration and download all platforms by default:"
379+ echo " git config --local --unset-all lfs.fetchexclude"
380+ """
381+
382+ with open (script_path , "w" , encoding = "utf-8" ) as f :
383+ f .write (script_content )
384+
385+ # Make the script executable on Unix-like systems
386+ if os .name != "nt" :
387+ script_path .chmod (script_path .stat ().st_mode | 0o755 )
388+
389+ tools_dir_str = replace_home_in_path (tools_dir , "~" )
390+ log (
391+ f"Generated LFS skip-smudge script: { tools_dir_str } /configure-lfs-skip-smudge.sh" ,
392+ "success" ,
393+ "📝" ,
394+ )
395+
396+
397+ def write_gitattributes_for_lfs (tools_dir : Path ) -> None :
398+ """Generate a .gitattributes file for Git LFS tracking of binary files.
399+
400+ Args:
401+ tools_dir: The base directory where tools are installed
402+
403+ """
404+ gitattributes_path = tools_dir / ".gitattributes"
405+
406+ # Common binary file extensions that should be tracked by LFS
407+ gitattributes_content = textwrap .dedent ("""\
408+ # Git LFS tracking for binary files
409+ # Generated by dotbins
410+
411+ # Track all files in platform directories as LFS
412+ linux/*/bin/* filter=lfs diff=lfs merge=lfs -text
413+ macos/*/bin/* filter=lfs diff=lfs merge=lfs -text
414+ windows/*/bin/* filter=lfs diff=lfs merge=lfs -text
415+
416+ # Track common binary extensions
417+ *.exe filter=lfs diff=lfs merge=lfs -text
418+ *.dll filter=lfs diff=lfs merge=lfs -text
419+ *.so filter=lfs diff=lfs merge=lfs -text
420+ *.dylib filter=lfs diff=lfs merge=lfs -text
421+ *.appimage filter=lfs diff=lfs merge=lfs -text
422+ *.AppImage filter=lfs diff=lfs merge=lfs -text
423+
424+ # Track archives (in case any are stored)
425+ *.zip filter=lfs diff=lfs merge=lfs -text
426+ *.tar filter=lfs diff=lfs merge=lfs -text
427+ *.tar.gz filter=lfs diff=lfs merge=lfs -text
428+ *.tgz filter=lfs diff=lfs merge=lfs -text
429+ *.tar.bz2 filter=lfs diff=lfs merge=lfs -text
430+ *.tar.xz filter=lfs diff=lfs merge=lfs -text
431+ *.7z filter=lfs diff=lfs merge=lfs -text
432+ *.rar filter=lfs diff=lfs merge=lfs -text
433+ """ )
434+
435+ with open (gitattributes_path , "w" , encoding = "utf-8" ) as f :
436+ f .write (gitattributes_content )
437+
438+ tools_dir_str = replace_home_in_path (tools_dir , "~" )
439+ log (f"Generated .gitattributes for LFS: { tools_dir_str } /.gitattributes" , "success" , "📝" )
440+
441+
299442STYLE_EMOJI_MAP = {
300443 "success" : "✅" ,
301444 "error" : "❌" ,
0 commit comments