bulk: syncr
This commit is contained in:
		
							parent
							
								
									f0e039461c
								
							
						
					
					
						commit
						344e1693bd
					
				
					 55 changed files with 1838 additions and 796 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | .data/ | ||||||
|  | target/ | ||||||
							
								
								
									
										12
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
										
									
									
									
								
							|  | @ -1,12 +0,0 @@ | ||||||
| # Raine's Dotfiles |  | ||||||
| 
 |  | ||||||
| ## Crates |  | ||||||
| Everything is a crate.   |  | ||||||
| If something is distro specific you should follow the following naming scheme: |  | ||||||
| `crate.<DISTRO>.sh` |  | ||||||
| 
 |  | ||||||
| ## Using it |  | ||||||
| Just use the script tbh |  | ||||||
| ```sh |  | ||||||
| curl -L https://via.ixvd.net/sh | sh |  | ||||||
| ``` |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     pacman -Syyu --noconfirm |  | ||||||
|     pacman -S --needed --noconfirm sudo reflector |  | ||||||
|     if ! grep -q "Reflector" /etc/pacman.d/mirrorlist; then |  | ||||||
|         cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak |  | ||||||
|         reflector -c NL -f 10 --threads 4 --save /etc/pacman.d/mirrorlist |  | ||||||
|     else |  | ||||||
|         echo "err: reflector already executed -- skipping..." |  | ||||||
|     fi |  | ||||||
| 
 |  | ||||||
|     cp files/pacman.conf /etc/pacman.conf |  | ||||||
| } |  | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     apt update -y |  | ||||||
|     apt install -y netselect-apt sudo |  | ||||||
|     netselect-apt |  | ||||||
| } |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| describe="Install stuff on the system!" |  | ||||||
| scripts="@distro @self" |  | ||||||
| 
 |  | ||||||
| super_apply() { |  | ||||||
|     if [ -f /usr/lib/security/pam_wheel.so ] && ! grep -q "# pam_wheel.so added" /etc/pam.d/su; then |  | ||||||
|         echo "auth           sufficient      pam_wheel.so trust use_uid" > /etc/pam.d/su |  | ||||||
|         echo "# pam_wheel.so added" > /etc/pam.d/su |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
|  | @ -1,31 +0,0 @@ | ||||||
| [options] |  | ||||||
| HoldPkg     = pacman glibc yay |  | ||||||
| Architecture = auto |  | ||||||
| 
 |  | ||||||
| Color |  | ||||||
| CheckSpace |  | ||||||
| ParallelDownloads = 5 |  | ||||||
| 
 |  | ||||||
| SigLevel    = Required DatabaseOptional |  | ||||||
| LocalFileSigLevel = Optional |  | ||||||
| 
 |  | ||||||
| #[testing] |  | ||||||
| #Include = /etc/pacman.d/mirrorlist |  | ||||||
| 
 |  | ||||||
| [core] |  | ||||||
| Include = /etc/pacman.d/mirrorlist |  | ||||||
| 
 |  | ||||||
| [extra] |  | ||||||
| Include = /etc/pacman.d/mirrorlist |  | ||||||
| 
 |  | ||||||
| #[community-testing] |  | ||||||
| #Include = /etc/pacman.d/mirrorlist |  | ||||||
| 
 |  | ||||||
| [community] |  | ||||||
| Include = /etc/pacman.d/mirrorlist |  | ||||||
| 
 |  | ||||||
| #[multilib-testing] |  | ||||||
| #Include = /etc/pacman.d/mirrorlist |  | ||||||
| 
 |  | ||||||
| [multilib] |  | ||||||
| Include = /etc/pacman.d/mirrorlist |  | ||||||
|  | @ -1,18 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| describe="setup ssh" |  | ||||||
| 
 |  | ||||||
| apply() { |  | ||||||
|     [ -e "$HOME/.ssh/authorized_keys" ] || ln files/authorized_keys $HOME/.ssh/authorized_keys |  | ||||||
|     [ -e "$HOME/.ssh/config" ] || ln files/config $HOME/.ssh/config |  | ||||||
|     if ! [ -f "$HOME/.ssh/id_rsa" ]; then |  | ||||||
|         echo "Creating new ssh key for this device..." |  | ||||||
|         ssh-keygen -f $HOME/.ssh/id_rsa -p "" -q |  | ||||||
|         echo "Adding key to authorized_keys..." |  | ||||||
|         cat $HOME/.ssh/id_rsa.pub > $HOME/.ssh/authorized_keys |  | ||||||
|     fi |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| undo() { |  | ||||||
|     echo "Undoing ssh keys is not supported, please do this manually." |  | ||||||
| } |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCeNQfnbyyF3sht43vH5BcXDPca8nWu6bKPVGvAlWBOq4Av8ME2IQgwVe9nJ05r73ZY02/Vdqc01a8wyK5Hmw0XlPL0Cn6wc9QoiscOvq5lMUK87S2tr3EVLGkgl8o7nmVuWgLewyojiORjM02P1PZEiFhKPXVEQFxU0dFz9QtpAdm0u78Xn2HTukHpXSv44R3XDDMFZ3Ek/XRuS6J9dZVxGkgCLQhK8kpfbxuiYxaRC7MHgGlYuxjLuZ6P4i+V+SSSShfCGdm6U9bgeIAwftN6a8Pc9+OsBeZGSUrGjZjRlD35q0a7fbpoS8pKTfbwgf/ijYeu3JmAQUlY+H959mIpg4H9XOgRrKVJSYwx5/BGuhmWgVy6HIYpXCQfEbLE7QDmwC2C430KzAH6jCcrRNyurIUCuO4iq9dwoQTzboMccOK79S2Z+1B5fYgS3BZgaiTUBSME2G2FriM6utgleiBnvFu/p7oH2I8ZHL/aVcSWAw0gbzsr7ADywAuiDNZk18c= strix@ryuk |  | ||||||
|  | @ -1,22 +0,0 @@ | ||||||
| ## neb servers |  | ||||||
| 
 |  | ||||||
| # hydrogen red helix |  | ||||||
| Host H |  | ||||||
|     Hostname hydrogen.red.helix.saluco.nl |  | ||||||
| 
 |  | ||||||
| # argon red helix |  | ||||||
| Host A |  | ||||||
|     Hostname argon.red.helix.saluco.nl |  | ||||||
| 
 |  | ||||||
| # iron red sphere |  | ||||||
| Host I |  | ||||||
|     Hostname iron.red.sphere.saluco.nl |  | ||||||
| 
 |  | ||||||
| ## utility servers |  | ||||||
| Host git |  | ||||||
|     Hostname git.saluco.nl |  | ||||||
|     User git |  | ||||||
| 
 |  | ||||||
| Host github |  | ||||||
|     Hostname github.com |  | ||||||
|     User git |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| pkgs="i3 i3lock i3status libpulse brightnessctl xss-lock dex maim dmenu gnome-keyring feh picom" |  | ||||||
| 
 |  | ||||||
| super_apply() { |  | ||||||
|     pacman -S --needed --noconfirm $pkgs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     pacman -R --noconfirm $pkgs |  | ||||||
| } |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| pkgs="i3 i3lock i3status libpulse-mainloop-glib brightnessctl xss-lock dex maim dmenu gnome-keyring feh picom" |  | ||||||
| 
 |  | ||||||
| super_apply() { |  | ||||||
|     apt install -y $pkgs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     apt remove -y $pkgs |  | ||||||
| } |  | ||||||
|  | @ -1,26 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| describe="Installs i3" |  | ||||||
| scripts="@distro @self" |  | ||||||
| 
 |  | ||||||
| apply() { |  | ||||||
|     [ -d "$HOME/.config/i3" ] || mkdir -p $HOME/.config/i3 |  | ||||||
|     [ -d "$HOME/.config/i3status" ] || mkdir -p $HOME/.config/i3status |  | ||||||
|     [ -e "$HOME/.config/i3/config" ] || ln files/config $HOME/.config/i3/config |  | ||||||
|     [ -e "$HOME/.config/i3status/config" ] || ln files/status_config $HOME/.config/i3status/config |  | ||||||
|     [ -e "$HOME/.config/picom.conf" ] || ln files/picom.conf $HOME/.config/picom.conf |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| undo() { |  | ||||||
|     rm $HOME/.config/i3/config |  | ||||||
|     rm $HOME/.config/i3status/config |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_apply() { |  | ||||||
|     [ -d "/etc/X11/xorg.conf.d" ] || mkdir -p /etc/X11/xorg.conf.d/ |  | ||||||
|     cp files/40-proper-touchpad.conf /etc/X11/xorg.conf.d/40-proper-touchpad.conf |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     rm /etc/X11/xorg.conf.d/40-proper-touchpad.conf |  | ||||||
| } |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| pkgs="i3 i3lock i3status pulseaudio-devel brightnessctl xss-lock dex maim dmenu gnome-keyring feh picom" |  | ||||||
| 
 |  | ||||||
| super_apply() { |  | ||||||
|     xbps-install -y $pkgs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     xbps-remove -y $pkgs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| Section "InputClass" |  | ||||||
|         Identifier "libinput touchpad catchall" |  | ||||||
|         MatchIsTouchpad "on" |  | ||||||
|         MatchDevicePath "/dev/input/event*" |  | ||||||
|         Driver "libinput" |  | ||||||
|         Option "NaturalScrolling" "True" |  | ||||||
|         Option "Tapping" "on" |  | ||||||
| EndSection |  | ||||||
|  | @ -1,206 +0,0 @@ | ||||||
| ####################### |  | ||||||
| ## Raine's i3 config ## |  | ||||||
| ## Mar 22, 2023      ## |  | ||||||
| ## mutation: 1m      ## |  | ||||||
| ####################### |  | ||||||
| 
 |  | ||||||
| ## Mostly similar to i3's config yet differs |  | ||||||
| 
 |  | ||||||
| # Useful variables: |  | ||||||
| # This section probably gets changed a lot |  | ||||||
| # --- |  | ||||||
| set $terminal alacritty |  | ||||||
| set $screen_lock i3lock -c "#111111" --nofork |  | ||||||
| set $appmenu i3-dmenu-desktop |  | ||||||
| 
 |  | ||||||
| set $screenshot maim -s | xclip -selection clipboard -t image/png |  | ||||||
| 
 |  | ||||||
| set $font pango:monospace 8 |  | ||||||
| 
 |  | ||||||
| # Startup Applications: |  | ||||||
| # Things that will startup when starting i3. |  | ||||||
| # --- |  | ||||||
| exec_always --no-startup-id dex --autostart --environment i3 |  | ||||||
| exec_always --no-startup-id nm-applet |  | ||||||
| exec_always --no-startup-id xss-lock --transfer-sleep-lock -- $screen_lock  |  | ||||||
| exec_always --no-startup-id gnome-keyring-daemon --start --components=ssh,secrets,pkcs11 |  | ||||||
| exec_always --no-startup-id feh --bg-fill ~/Pictures/wallpaper.jpg |  | ||||||
| exec_always --no-startup-id picom |  | ||||||
| 
 |  | ||||||
| # Gaps & Borders: |  | ||||||
| # --- |  | ||||||
| gaps inner 10 |  | ||||||
| smart_gaps on |  | ||||||
| 
 |  | ||||||
| default_border pixel 1 |  | ||||||
| hide_edge_borders smart_no_gaps |  | ||||||
| 
 |  | ||||||
| # Extra variables: |  | ||||||
| # Only need changing for very specific installations. |  | ||||||
| # --- |  | ||||||
| set $audio_volume_up XF86AudioRaiseVolume |  | ||||||
| set $audio_volume_down XF86AudioLowerVolume |  | ||||||
| set $audio_mute XF86AudioMute |  | ||||||
| set $audio_mute_mic XF86AudioMicMute |  | ||||||
| 
 |  | ||||||
| set $brightness_up XF86MonBrightnessUp |  | ||||||
| set $brightness_down XF86MonBrightnessDown |  | ||||||
| 
 |  | ||||||
| set $ws_1 "1:main" |  | ||||||
| set $ws_2 "2:term" |  | ||||||
| set $ws_3 "3:docs" |  | ||||||
| set $ws_4 "4:mail" |  | ||||||
| set $ws_5 "5" |  | ||||||
| set $ws_6 "6" |  | ||||||
| set $ws_7 "7" |  | ||||||
| set $ws_8 "8" |  | ||||||
| set $ws_9 "9:bg" |  | ||||||
| set $ws_10 "10:misc" |  | ||||||
| 
 |  | ||||||
| set $meta_refresh_statusbar killall -SIGUSR1 i3status |  | ||||||
| bar { |  | ||||||
|     strip_workspace_numbers yes |  | ||||||
|     status_command i3status |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| # END OF CONFIG |  | ||||||
| 
 |  | ||||||
| set $mod Mod4 |  | ||||||
| set $alt Mod1 |  | ||||||
| 
 |  | ||||||
| # Customization |  | ||||||
| 
 |  | ||||||
| # class                   border  backgr. text    indic.   child_border |  | ||||||
| client.focused            #81A1C1 #81A1C1 #ffffff #D8DEE9 |  | ||||||
| client.focused_inactive   #2E3440 #2E3440 #88C0D0 #454948 |  | ||||||
| client.unfocused          #2E3440 #2E3440 #88C0D0 #454948 |  | ||||||
| client.urgent             #D08770 #3B4252 #ffffff #268BD2 |  | ||||||
| client.placeholder        #000000 #0c0c0c #ffffff #000000 |  | ||||||
| client.background         #3B4252 |  | ||||||
| 
 |  | ||||||
| # Generic |  | ||||||
| floating_modifier $mod |  | ||||||
| tiling_drag modifier titlebar |  | ||||||
| font $font |  | ||||||
| 
 |  | ||||||
| # Open a terminal |  | ||||||
| bindsym $mod+Return exec $terminal |  | ||||||
| 
 |  | ||||||
| # Kill current window |  | ||||||
| bindsym $mod+$alt+q kill |  | ||||||
| 
 |  | ||||||
| # Open app menu |  | ||||||
| bindsym $mod+d exec --no-startup-id $appmenu  |  | ||||||
| 
 |  | ||||||
| # Lock screen |  | ||||||
| bindsym $mod+l exec --no-startup-id $screen_lock |  | ||||||
| 
 |  | ||||||
| # Screenshots |  | ||||||
| bindsym Print exec --no-startup-id $screenshot |  | ||||||
| 
 |  | ||||||
| # Audio |  | ||||||
| bindsym $audio_volume_up exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $meta_refresh_statusbar |  | ||||||
| bindsym $audio_volume_down exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $meta_refresh_statusbar |  | ||||||
| bindsym $audio_mute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $meta_refresh_statusbar |  | ||||||
| bindsym $audio_mute_mic exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $meta_refresh_statusbar |  | ||||||
| 
 |  | ||||||
| # Brightness |  | ||||||
| bindsym $brightness_up exec --no-startup-id brightnessctl set +5% && $meta_refresh_statusbar |  | ||||||
| bindsym $brightness_down exec --no-startup-id brightnessctl set 5%- && $meta_refresh_statusbar |  | ||||||
| 
 |  | ||||||
| # Change focused window |  | ||||||
| bindsym $mod+Up focus up |  | ||||||
| bindsym $mod+Down focus down |  | ||||||
| bindsym $mod+Left focus left |  | ||||||
| bindsym $mod+Right focus right |  | ||||||
| 
 |  | ||||||
| # Move focused window |  | ||||||
| bindsym $mod+Shift+Up move up |  | ||||||
| bindsym $mod+Shift+Down move down |  | ||||||
| bindsym $mod+Shift+Left move left |  | ||||||
| bindsym $mod+Shift+Right move right |  | ||||||
| 
 |  | ||||||
| # Splits |  | ||||||
| bindsym $mod+Shift+h split h |  | ||||||
| bindsym $mod+Shift+v split v |  | ||||||
| 
 |  | ||||||
| # Change container layout |  | ||||||
| bindsym $mod+Shift+s layout stacking |  | ||||||
| bindsym $mod+Shift+t layout tabbed |  | ||||||
| bindsym $mod+Shift+d layout toggle split |  | ||||||
| 
 |  | ||||||
| # Make current window fullscreen |  | ||||||
| bindsym $mod+Shift+f fullscreen toggle |  | ||||||
| 
 |  | ||||||
| # Floating stuff |  | ||||||
| bindsym $mod+space focus mode_toggle |  | ||||||
| bindsym $mod+Shift+space floating toggle |  | ||||||
| 
 |  | ||||||
| # Scratchpad |  | ||||||
| bindsym $mod+Shift+minus move scratchpad |  | ||||||
| bindsym $mod+minus scratchpad show |  | ||||||
| 
 |  | ||||||
| # Switch to workspace |  | ||||||
| bindsym $mod+1 workspace $ws_1 |  | ||||||
| bindsym $mod+2 workspace $ws_2 |  | ||||||
| bindsym $mod+3 workspace $ws_3 |  | ||||||
| bindsym $mod+4 workspace $ws_4 |  | ||||||
| bindsym $mod+5 workspace $ws_5 |  | ||||||
| bindsym $mod+6 workspace $ws_6 |  | ||||||
| bindsym $mod+7 workspace $ws_7 |  | ||||||
| bindsym $mod+8 workspace $ws_8 |  | ||||||
| bindsym $mod+9 workspace $ws_9 |  | ||||||
| bindsym $mod+0 workspace $ws_10 |  | ||||||
| 
 |  | ||||||
| # Move focused container to workspace |  | ||||||
| bindsym $mod+Shift+1 move container to workspace $ws_1 |  | ||||||
| bindsym $mod+Shift+2 move container to workspace $ws_2 |  | ||||||
| bindsym $mod+Shift+3 move container to workspace $ws_3 |  | ||||||
| bindsym $mod+Shift+4 move container to workspace $ws_4 |  | ||||||
| bindsym $mod+Shift+5 move container to workspace $ws_5 |  | ||||||
| bindsym $mod+Shift+6 move container to workspace $ws_6 |  | ||||||
| bindsym $mod+Shift+7 move container to workspace $ws_7 |  | ||||||
| bindsym $mod+Shift+8 move container to workspace $ws_8 |  | ||||||
| bindsym $mod+Shift+9 move container to workspace $ws_9 |  | ||||||
| bindsym $mod+Shift+0 move container to workspace $ws_10 |  | ||||||
| 
 |  | ||||||
| # Move through workspaces |  | ||||||
| bindsym $mod+$alt+Left workspace prev |  | ||||||
| bindsym $mod+$alt+Right workspace next |  | ||||||
| 
 |  | ||||||
| # WM stuff |  | ||||||
| # reload i3 config |  | ||||||
| bindsym $mod+$alt+c reload |  | ||||||
| # restart i3 |  | ||||||
| bindsym $mod+$alt+r restart |  | ||||||
| # exit i3 |  | ||||||
| bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'Exit i3?' -B 'Yes, exit i3' 'i3-msg exit'" |  | ||||||
| 
 |  | ||||||
| # Modes |  | ||||||
| bindsym $mod+r mode resize |  | ||||||
| mode "resize" { |  | ||||||
|     bindsym $nav_left   resize shrink width 10 px or 10 ppt |  | ||||||
|     bindsym $nav_down   resize grow height 10 px or 10 ppt |  | ||||||
|     bindsym $nav_up     resize shrink height 10 px or 10 ppt |  | ||||||
|     bindsym $nav_right  resize grow width 10 px or 10 ppt |  | ||||||
|     bindsym Left        resize shrink width 10 px or 10 ppt |  | ||||||
|     bindsym Down        resize grow height 10 px or 10 ppt |  | ||||||
|     bindsym Up          resize shrink height 10 px or 10 ppt |  | ||||||
|     bindsym Right       resize grow width 10 px or 10 ppt |  | ||||||
| 
 |  | ||||||
|     bindsym Return mode "default" |  | ||||||
|     bindsym Escape mode "default" |  | ||||||
|     bindsym $mod+r mode "default" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bindsym $mod+s mode "session" |  | ||||||
| mode "session" { |  | ||||||
|     bindsym l exec --no-startup-id $lock, mode "default" |  | ||||||
|     bindsym e exec --no-startup-id i3-msg exit, mode "default" |  | ||||||
|     bindsym Shift+r exec --no-startup-id systemctl reboot, mode "default" |  | ||||||
|     bindsym Shift+s exec --no-startup-id systemctl poweroff -i, mode "default" |  | ||||||
| 
 |  | ||||||
|     bindsym Return mode "default" |  | ||||||
|     bindsym Escape mode "default" |  | ||||||
|     bindsym $mod+s mode "default" |  | ||||||
| } |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| inactive-opacity = 0.75; |  | ||||||
| 
 |  | ||||||
| blur: { |  | ||||||
|   method = "box"; |  | ||||||
|   size = 10; |  | ||||||
|   background = false; |  | ||||||
|   background-frame = false; |  | ||||||
|   background-fixed = false; |  | ||||||
| } |  | ||||||
|  | @ -1,57 +0,0 @@ | ||||||
| general { |  | ||||||
|         output_format = "i3bar" |  | ||||||
|         colors = true |  | ||||||
|         interval = 5 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| order += "ipv6" |  | ||||||
| order += "wireless wlp58s0" |  | ||||||
| order += "battery 0" |  | ||||||
| order += "disk /" |  | ||||||
| order += "memory" |  | ||||||
| order += "load" |  | ||||||
| order += "tztime local" |  | ||||||
| 
 |  | ||||||
| wireless wlp58s0 { |  | ||||||
|         format_up = "W: (%quality at %essid, %bitrate) %ip" |  | ||||||
|         format_down = "W: down" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| battery 0 { |  | ||||||
|         format = "%status %percentage %remaining %emptytime" |  | ||||||
|         format_down = "No battery" |  | ||||||
|         status_chr = "⚡ CHR" |  | ||||||
|         status_bat = "🔋 BAT" |  | ||||||
|         status_unk = "? UNK" |  | ||||||
|         status_full = "☻ FULL" |  | ||||||
|         path = "/sys/class/power_supply/BAT%d/uevent" |  | ||||||
|         low_threshold = 10 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| tztime local { |  | ||||||
|         format = "%Y-%m-%d %H:%M:%S" |  | ||||||
|         hide_if_equals_localtime = false |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| tztime berlin { |  | ||||||
|         format = "%Y-%m-%d %H:%M:%S %Z" |  | ||||||
|         timezone = "Europe/Berlin" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| load { |  | ||||||
|         format = "%5min" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| memory { |  | ||||||
|         format = "%used" |  | ||||||
|         threshold_degraded = "10%" |  | ||||||
|         format_degraded = "MEMORY: %free" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| disk "/" { |  | ||||||
|         format = "%free" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| read_file uptime { |  | ||||||
|         path = "/proc/uptime" |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     pacman -S --needed --noconfirm zsh |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     pacman -R --noconfirm zsh |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     apt install -y zsh |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     apt remove -y zsh |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     apt install -y zsh |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     apt remove -y zsh |  | ||||||
| } |  | ||||||
|  | @ -1,31 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| describe="Install zsh and oh-my-zsh!" |  | ||||||
| scripts="@distro @self" |  | ||||||
| 
 |  | ||||||
| super_apply() { |  | ||||||
|     usermod $USER --shell /bin/zsh |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     usermod $USER --shell /bin/bash |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| apply() { |  | ||||||
|     if [ ! -d "$HOME/.oh-my-zsh" ]; then |  | ||||||
|         sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended |  | ||||||
| 
 |  | ||||||
|         PL_DIR=${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions |  | ||||||
|         [ -d "$PL_DIR" ] || git clone https://github.com/zsh-users/zsh-autosuggestions $PL_DIR |  | ||||||
|         PL_DIR=${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting |  | ||||||
|         [ -d "$PL_DIR" ] || git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $PL_DIR |  | ||||||
|     fi |  | ||||||
| 
 |  | ||||||
|     [ -f "$HOME/.zshrc" ] && unlink $HOME/.zshrc |  | ||||||
|     [ -e "$HOME/.zshrc" ] || ln files/.zshrc $HOME/.zshrc |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| undo() { |  | ||||||
|     unlink $HOME/.zshrc |  | ||||||
|     rm -rf $HOME/.oh-my-zsh |  | ||||||
| } |  | ||||||
|  | @ -1,10 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| super_apply() { |  | ||||||
|     xbps-install -y zsh |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     xbps-remove -y zsh |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | @ -1,44 +0,0 @@ | ||||||
| #!/bin/zsh |  | ||||||
| 
 |  | ||||||
| # Raine's .zshrc |  | ||||||
| 
 |  | ||||||
| if [ "$PROFILEINC" = "1" ]; then |  | ||||||
| 	. ~/.profile |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| export EDITOR=vim |  | ||||||
| export GPG_TTY=$(tty) |  | ||||||
| export PATH="$PATH:$HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$HOME/.local/bin" |  | ||||||
| 
 |  | ||||||
| # oh-my-zsh init |  | ||||||
| if [ -f "$HOME/.oh-my-zsh/oh-my-zsh.sh" ]; then |  | ||||||
|     export ZSH="$HOME/.oh-my-zsh" |  | ||||||
|     ZSH_THEME="afowler" |  | ||||||
|     plugins=(git docker docker-compose node zsh-autosuggestions zsh-syntax-highlighting zsh-cargo-completion) |  | ||||||
|     source $ZSH/oh-my-zsh.sh |  | ||||||
| else |  | ||||||
| 	echo "oh-my-zsh not detected :(" |  | ||||||
|     PS1="$(whoami)@${HOSTNAME:-$(hostname)} $ " |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| update_dotfiles() { |  | ||||||
|     cd $HOME/.dotfiles |  | ||||||
|     git pull |  | ||||||
|     cd - &> /dev/null |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| container() { |  | ||||||
| 	docker run \ |  | ||||||
| 		-ti \ |  | ||||||
| 		--rm \ |  | ||||||
| 		--name tmp-$(id -u)-$(openssl rand -hex 8) \ |  | ||||||
| 		--network ${CONTAINER_NETWORK:-internal} \ |  | ||||||
| 		alpine \ |  | ||||||
| 		ash |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| [ -f "$HOME/.config/i3/shortcuts-i3.sh" ] && . ~/.config/i3/shortcuts-i3.sh |  | ||||||
| 
 |  | ||||||
| alias q="exit" |  | ||||||
| alias vim="nvim" |  | ||||||
| alias vi="nvim" |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     pacman -S --needed --noconfirm neovim |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     echo "we never uninstall vim -_-" |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     apt install -y neovim |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     echo "we never uninstall vim -_-" |  | ||||||
| } |  | ||||||
|  | @ -1,15 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| describe="Install vim and it's stuff" |  | ||||||
| scripts="@distro @self" |  | ||||||
| 
 |  | ||||||
| apply() { |  | ||||||
|     [ -d "$HOME/.config/nvim" ] || mkdir -p "$HOME/.config/nvim" |  | ||||||
|     [ -e "$HOME/.config/nvim/init.vim" ] || ln files/init.vim $HOME/.config/nvim/init.vim |  | ||||||
|     [ -e "$HOME/.ideavimrc" ] || ln files/.ideavimrc $HOME/.ideavimrc |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| undo() { |  | ||||||
|     unlink $HOME/.config/nvim/init.vim |  | ||||||
|     unlink $HOME/.ideavimrc |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     xbps-install -y neovim |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     echo "we never uninstall vim -_-" |  | ||||||
| } |  | ||||||
|  | @ -1,10 +0,0 @@ | ||||||
| source ~/.vimrc |  | ||||||
| 
 |  | ||||||
| set scrolloff=5 |  | ||||||
| set incsearch |  | ||||||
| 
 |  | ||||||
| map Q gq |  | ||||||
| 
 |  | ||||||
| Plug 'machakann/vim-highlightedyank' |  | ||||||
| Plug 'tpope/vim-commentary' |  | ||||||
| Plug 'wellle/targets.vim' |  | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| " vim preferences |  | ||||||
| set number |  | ||||||
| set relativenumber |  | ||||||
| syntax on |  | ||||||
| 
 |  | ||||||
| " No arrow keys |  | ||||||
| noremap <Up> <Nop> |  | ||||||
| noremap <Down> <Nop> |  | ||||||
| noremap <Left> <Nop> |  | ||||||
| noremap <Right> <Nop> |  | ||||||
| 
 |  | ||||||
| " ensure vim-plug |  | ||||||
| let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim' |  | ||||||
| if empty(glob(data_dir . '/autoload/plug.vim')) |  | ||||||
|   silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' |  | ||||||
|   autocmd VimEnter * PlugInstall --sync | source $MYVIMRC |  | ||||||
| endif |  | ||||||
| 
 |  | ||||||
| call plug#begin() |  | ||||||
| 
 |  | ||||||
| Plug 'ThePrimeagen/vim-be-good' |  | ||||||
| Plug 'machakann/vim-highlightedyank' |  | ||||||
| Plug 'tpope/vim-commentary' |  | ||||||
| Plug 'wellle/targets.vim' |  | ||||||
| Plug 'vim-scripts/loremipsum' |  | ||||||
| 
 |  | ||||||
| call plug#end() |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     pacman -S --needed --noconfirm alacritty |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     pacman -R --noconfirm alacritty |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     apt install -y alacritty |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     apt remove -y alacritty |  | ||||||
| } |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| describe="Installs alacritty and configs" |  | ||||||
| scripts="@distro @self" |  | ||||||
| 
 |  | ||||||
| apply() { |  | ||||||
|     [ -d "$HOME/.config/alacritty" ] || mkdir -p $HOME/.config/alacritty |  | ||||||
|     [ -e "$HOME/.config/alacritty/alacritty.yml" ] || ln files/alacritty.yml $HOME/.config/alacritty/alacritty.yml |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| undo() { |  | ||||||
|     unlink $HOME/.config/alacritty/alacritty.yml |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| super_apply() { |  | ||||||
|     xbps-install -y alacritty |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| super_undo() { |  | ||||||
|     xbps-remove -y alacritty |  | ||||||
| } |  | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| cursor: |  | ||||||
|   style: |  | ||||||
|     shape: 'Block' |  | ||||||
|     blinking: 'On' |  | ||||||
|   blink_interval: 500 |  | ||||||
| 
 |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| describe="Setup git" |  | ||||||
| scripts="@distro @self" |  | ||||||
| 
 |  | ||||||
| apply() { |  | ||||||
|     git config --global user.name Strix |  | ||||||
|     git config --global user.email strix@saluco.nl |  | ||||||
| } |  | ||||||
							
								
								
									
										23
									
								
								crates/common/crate.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								crates/common/crate.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | name = "common" | ||||||
|  | description = "Common set of utilities" | ||||||
|  | 
 | ||||||
|  | [pkgs] | ||||||
|  | openssh-server = {} | ||||||
|  | openssh-client = {} | ||||||
|  | git = {} | ||||||
|  | netselect = { distros = ["debian", "ubuntu"] } | ||||||
|  | reflector = { distros = ["arch"] } | ||||||
|  | 
 | ||||||
|  | [actions] | ||||||
|  | setup_ssh = ["sh", "./scripts/%"] | ||||||
|  | reflector = { args = ["sh", "./scripts/setup_pm/%"], distro = ["arch"] } | ||||||
|  | netselect = { args = [ | ||||||
|  |   "sh", | ||||||
|  |   "./scripts/setup_pm/%", | ||||||
|  | ], distro = [ | ||||||
|  |   "debian", | ||||||
|  |   "ubuntu", | ||||||
|  | ] } | ||||||
|  | 
 | ||||||
|  | [super_actions] | ||||||
|  | pam_wheel = ["sh", "./scripts/%"] | ||||||
							
								
								
									
										4
									
								
								crates/common/scripts/pam_wheel.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								crates/common/scripts/pam_wheel.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | if [ -f /usr/lib/security/pam_wheel.so ] && ! grep -q "# pam_wheel.so added" /etc/pam.d/su; then | ||||||
|  |     echo "auth           sufficient      pam_wheel.so trust use_uid" > /etc/pam.d/su | ||||||
|  |     echo "# pam_wheel.so added" > /etc/pam.d/su | ||||||
|  | fi | ||||||
							
								
								
									
										89
									
								
								dot
									
										
									
									
									
								
							
							
						
						
									
										89
									
								
								dot
									
										
									
									
									
								
							|  | @ -1,89 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| ask=0 |  | ||||||
| 
 |  | ||||||
| is_function() { |  | ||||||
|     type "$1" 2>/dev/null | sed "s/$1//" | grep -qwi function |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| curr_distro() { |  | ||||||
|     cat /etc/os-release | grep -G "^ID=" | sed 's/ID=//' |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| include() { |  | ||||||
|     [ -f "$1" ] || return 1 |  | ||||||
|     . $1 |  | ||||||
|     return 0 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func() { |  | ||||||
|     if is_function $(echo "super_$2"); then |  | ||||||
|         [ "${DO_SUDO:-yes}" = "yes" ] || return 0 |  | ||||||
|         ecmd=". $1 && super_$2" |  | ||||||
|         [ "$(id -u)" = "0" ] && sh -c "$ecmd" || sudo sh -c "$ecmd" |  | ||||||
|         unset ecmd |  | ||||||
|     fi |  | ||||||
|     is_function $2 && $2 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| # only run this *in crate dir* |  | ||||||
| run_crate() { |  | ||||||
|     enabled=1 |  | ||||||
|     include ./crate.sh || exit 1 |  | ||||||
|     if [ -n "$describe" ]; then |  | ||||||
|         echo "desc($(basename $PWD)): $describe" |  | ||||||
|     fi |  | ||||||
|     if [ $enabled -ne 1 ]; then |  | ||||||
|         return |  | ||||||
|     fi |  | ||||||
|     cmd=$1 |  | ||||||
|     scripts=${scripts:-"@self @distro"} |  | ||||||
|     for s in $scripts; do |  | ||||||
|         echo "exec($(basename $PWD)): $s/$cmd" |  | ||||||
|         case $s in |  | ||||||
|         @self) |  | ||||||
|             func ./crate.sh $cmd |  | ||||||
|             ;; |  | ||||||
|         @distro) |  | ||||||
|             unset -f super_$cmd |  | ||||||
|             unset -f $cmd |  | ||||||
|             include ./crate.$(curr_distro).sh |  | ||||||
|             func ./crate.$(curr_distro).sh $cmd |  | ||||||
|             unset -f super_$cmd |  | ||||||
|             unset -f $cmd |  | ||||||
|             include ./crate.sh |  | ||||||
|             ;; |  | ||||||
|         *) |  | ||||||
|             sh $s |  | ||||||
|             ;; |  | ||||||
|         esac |  | ||||||
|     done |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| echo "# details:" |  | ||||||
| echo "# user: $USER (${UID:-$(id -u)})" |  | ||||||
| echo "# groups: $(groups)" |  | ||||||
| echo "# distro: $(curr_distro)" |  | ||||||
| 
 |  | ||||||
| cmd=$1 |  | ||||||
| if [ -z "$cmd" ]; then |  | ||||||
|     echo "usage: $0 <command> [...args]" |  | ||||||
|     exit 1 |  | ||||||
| else |  | ||||||
|     shift |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| for c in ${@:-$(ls crates)}; do |  | ||||||
|     [ -d crates/*$c ] || exit 1 |  | ||||||
|     cd crates/*$c |  | ||||||
|     case $cmd in |  | ||||||
|     a | apply) |  | ||||||
|         run_crate apply |  | ||||||
|         ;; |  | ||||||
|     u | undo) |  | ||||||
|         run_crate undo |  | ||||||
|         ;; |  | ||||||
|     *) exit 1 ;; |  | ||||||
|     esac |  | ||||||
|     cd ../.. |  | ||||||
| done |  | ||||||
|  | @ -1,14 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| # this script is meant to be ran when .dotfiles is not present. |  | ||||||
| #  |  | ||||||
| # example: |  | ||||||
| # curl https://git.saluco.nl/strix/dotfiles/raw/branch/main/remote_script.sh | sh |  | ||||||
| 
 |  | ||||||
| set -e |  | ||||||
| 
 |  | ||||||
| HOME=${HOME:-/home/${USER:-$(whomai)}} |  | ||||||
| 
 |  | ||||||
| [ -d "$HOME/.dotfiles" ] || git clone https://git.saluco.nl/strix/dotfiles $HOME/.dotfiles |  | ||||||
| cd $HOME/.dotfiles |  | ||||||
| ./dot a |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| set -e |  | ||||||
| 
 |  | ||||||
| echo "Downloading newest package..." |  | ||||||
| curl -Lo /tmp/discord.deb "https://discord.com/api/download?platform=linux&format=deb" |  | ||||||
| cd /tmp |  | ||||||
| echo "Extracting package..." |  | ||||||
| xdeb discord.deb |  | ||||||
| echo "Installing package..." |  | ||||||
| sudo xbps-install -R /tmp/binpkgs discord |  | ||||||
| rm -rf /tmp/binpkgs |  | ||||||
| cd - |  | ||||||
							
								
								
									
										1149
									
								
								sync-runner/Cargo.lock
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1149
									
								
								sync-runner/Cargo.lock
									
										
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										20
									
								
								sync-runner/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								sync-runner/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | [package] | ||||||
|  | name = "sync-runner" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | clap = { version = "4.5.29", features = ["derive"] } | ||||||
|  | colored = "3.0.0" | ||||||
|  | execute = "0.2.13" | ||||||
|  | fern = "0.7.1" | ||||||
|  | git2 = "0.20.0" | ||||||
|  | glob = "0.3.2" | ||||||
|  | hex = "0.4.3" | ||||||
|  | lazy_static = "1.5.0" | ||||||
|  | log = "0.4.26" | ||||||
|  | regex = "1.11.1" | ||||||
|  | serde = { version = "1.0.218", features = ["serde_derive"] } | ||||||
|  | sha2 = "0.10.8" | ||||||
|  | shellexpand = "3.1.0" | ||||||
|  | toml = "0.8.20" | ||||||
							
								
								
									
										11
									
								
								sync-runner/package_manager.list
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								sync-runner/package_manager.list
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | install(pacman): pacman -Sy %args | ||||||
|  | uninstall(pacman): pacman -Rn %args | ||||||
|  | 
 | ||||||
|  | install(apt): apt install %args | ||||||
|  | uninstall(apt): apt remove %args | ||||||
|  | 
 | ||||||
|  | install(dnf): dnf install %args | ||||||
|  | uninstall(dnf): dnf remove %args | ||||||
|  | 
 | ||||||
|  | install(yum): yum install %args | ||||||
|  | uninstall(yum): yum remove %args | ||||||
							
								
								
									
										10
									
								
								sync-runner/src/action.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								sync-runner/src/action.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | use clap::Parser; | ||||||
|  | 
 | ||||||
|  | #[derive(Parser, Debug)] | ||||||
|  | pub enum Action { | ||||||
|  |     /// Sync your device with dotfiles repository
 | ||||||
|  |     Sync { | ||||||
|  |         #[arg(short, long)] | ||||||
|  |         config_path: Option<String>, | ||||||
|  |     }, | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								sync-runner/src/cfg/daemon.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								sync-runner/src/cfg/daemon.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | 
 | ||||||
|  | #[derive(Serialize, Deserialize, Debug)] | ||||||
|  | pub struct Daemon { | ||||||
|  |     /// interval in minutes
 | ||||||
|  |     pub interval: u64, | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								sync-runner/src/cfg/mod.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								sync-runner/src/cfg/mod.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | 
 | ||||||
|  | #![allow(unused)] | ||||||
|  | 
 | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | 
 | ||||||
|  | mod daemon; | ||||||
|  | 
 | ||||||
|  | #[derive(Serialize, Deserialize, Debug)] | ||||||
|  | pub struct Config { | ||||||
|  |     pub title: String, | ||||||
|  |     pub daemon: daemon::Daemon, | ||||||
|  |     pub source: HashMap<String, crate::source::Source> | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								sync-runner/src/crates/mod.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								sync-runner/src/crates/mod.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | 
 | ||||||
|  | mod pm; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Serialize, Deserialize)] | ||||||
|  | pub struct Package { | ||||||
|  |     name: String, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Package { | ||||||
|  |     pub fn install(&self) { | ||||||
|  |         todo!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn uninstall(&self) { | ||||||
|  |         todo!() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Serialize, Deserialize)] | ||||||
|  | pub struct CrateAction { | ||||||
|  |     pub name: String, | ||||||
|  |     pub command: String, | ||||||
|  |     pub args: Vec<String>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Serialize, Deserialize)] | ||||||
|  | pub struct Crate { | ||||||
|  |     pub pkgs: HashMap<String, Package>, | ||||||
|  |     pub actions: HashMap<String, CrateAction>, | ||||||
|  |     pub super_actions: HashMap<String, CrateAction>, | ||||||
|  | } | ||||||
							
								
								
									
										90
									
								
								sync-runner/src/crates/pm.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								sync-runner/src/crates/pm.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,90 @@ | ||||||
|  | use lazy_static::lazy_static; | ||||||
|  | use regex::Regex; | ||||||
|  | use std::{process::Command, str::FromStr}; | ||||||
|  | 
 | ||||||
|  | const pm_cfg: &str = include_str!("../../package_manager.list"); | ||||||
|  | 
 | ||||||
|  | /// regex: `(?<pm>[a-z]+)>(?<action>(?:un)?install+): (?<command>.*)`
 | ||||||
|  | /// example: pacman>install: pacman -Sy %args
 | ||||||
|  | 
 | ||||||
|  | lazy_static! { | ||||||
|  |     static ref PM_REGEX: Regex = | ||||||
|  |         Regex::new(r"(?P<pm>[a-z]+)>(?P<action>(?:un)?install+): (?P<command>.*)").unwrap(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct PackageManager { | ||||||
|  |     name: String, | ||||||
|  |     command: String, | ||||||
|  |     args: Vec<String>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl PackageManager { | ||||||
|  |     fn new(name: &str, command: &str, args: Vec<String>) -> Self { | ||||||
|  |         Self { | ||||||
|  |             name: name.to_string(), | ||||||
|  |             command: command.to_string(), | ||||||
|  |             args, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn install(&self, packages: Vec<String>) -> Result<(), Vec<String>> { | ||||||
|  |         Command::new(&self.command) | ||||||
|  |             .args(&self.args) | ||||||
|  |             .args(packages) | ||||||
|  |             .spawn() | ||||||
|  |             .expect("err"); | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  |     pub fn uninstall(&self, packages: Vec<String>) -> Result<(), Vec<String>> { | ||||||
|  |         todo!(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | impl FromStr for PackageManager { | ||||||
|  |     type Err = String; | ||||||
|  |     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||||
|  |         let caps = PM_REGEX.captures(s).ok_or("invalid package manager")?; | ||||||
|  |         let name = caps.name("pm").ok_or("invalid package manager")?.as_str(); | ||||||
|  |         let command = caps | ||||||
|  |             .name("command") | ||||||
|  |             .ok_or("invalid package manager")? | ||||||
|  |             .as_str(); | ||||||
|  |         let args = caps | ||||||
|  |             .name("args") | ||||||
|  |             .ok_or("invalid package manager")? | ||||||
|  |             .as_str() | ||||||
|  |             .split_whitespace() | ||||||
|  |             .map(|s| s.to_string()) | ||||||
|  |             .collect(); | ||||||
|  |         Ok(Self::new(name, command, args)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct Package { | ||||||
|  |     name: String, | ||||||
|  | } | ||||||
|  | impl FromStr for Package { | ||||||
|  |     type Err = String; | ||||||
|  |     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||||
|  |         let caps = PM_REGEX.captures(s).ok_or("invalid package")?; | ||||||
|  |         let name = caps.name("name").ok_or("invalid package")?.as_str(); | ||||||
|  |         Ok(Self::new(name)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Package { | ||||||
|  |     fn new(name: &str) -> Self { | ||||||
|  |         Self { | ||||||
|  |             name: name.to_string(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn package_managers() -> Vec<PackageManager> { | ||||||
|  |     pm_cfg | ||||||
|  |         .lines() | ||||||
|  |         .map(|s| s.to_string()) | ||||||
|  |         .map(|s| s.parse::<PackageManager>()) | ||||||
|  |         .collect::<Result<Vec<PackageManager>, String>>() | ||||||
|  |         .expect("invalid package manager") | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								sync-runner/src/logging.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								sync-runner/src/logging.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | ||||||
|  | use std::env; | ||||||
|  | 
 | ||||||
|  | use colored::Colorize; | ||||||
|  | use fern::Dispatch; | ||||||
|  | use log::{Record, SetLoggerError}; | ||||||
|  | 
 | ||||||
|  | fn format_regular<S: Into<String>>(log: S, record: &Record) -> String { | ||||||
|  |     let log = log.into(); | ||||||
|  |     let line_prefix = |line: String, extend: bool| { | ||||||
|  |         let prefix = if extend { | ||||||
|  |             match record.level() { | ||||||
|  |                 log::Level::Trace => "      ]".bright_blue(), | ||||||
|  |                 log::Level::Debug => " ?".green(), | ||||||
|  |                 log::Level::Info => " >".blue(), | ||||||
|  |                 log::Level::Warn => " #".yellow(), | ||||||
|  |                 log::Level::Error => " !".red(), | ||||||
|  |             }.to_string() | ||||||
|  |         } else { | ||||||
|  |             match record.level() { | ||||||
|  |                 log::Level::Trace => "[TRACE]".bright_blue().italic(), | ||||||
|  |                 log::Level::Debug => "??".green(), | ||||||
|  |                 log::Level::Info => "=>".blue(), | ||||||
|  |                 log::Level::Warn => "##".yellow(), | ||||||
|  |                 log::Level::Error => "!!".red().bold() | ||||||
|  |             }.to_string() | ||||||
|  |         }; | ||||||
|  |         return format!("{} {}", prefix, line); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let mut lines = log.lines().peekable(); | ||||||
|  |     let mut output = match lines.peek() { | ||||||
|  |         Some(_line) => line_prefix(lines.next().unwrap().to_string(), false), | ||||||
|  |         None => return "".to_string(), | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     for line in lines { | ||||||
|  |         output.push_str(&*format!("\n{}", line_prefix(line.to_string(), true))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     output | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn setup_logger() -> Result<(), SetLoggerError> { | ||||||
|  |     Dispatch::new() | ||||||
|  |         .format(|out, message, record| { | ||||||
|  |             match record.metadata().target() { | ||||||
|  |                 // command output logging
 | ||||||
|  |                 "command:stdout" => out.finish(format_args!("{} {}", ">>".cyan(), message.to_string())), | ||||||
|  |                 "command:stderr" => out.finish(format_args!("{} {}", ">>".red(), message.to_string())), | ||||||
|  |                 // this target means, it's an item and not a log.
 | ||||||
|  |                 "item" => out.finish(format_args!("{} {}", "*".blue(), message.to_string())), | ||||||
|  |                 // default logging
 | ||||||
|  |                 _ => out.finish(format_args!("{}", format_regular(message.to_string(), record))), | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .level( | ||||||
|  |             env::var("SYNCR_LOG_LEVEL") | ||||||
|  |                 .unwrap_or_else(|_| "info".to_string()) | ||||||
|  |                 .parse() | ||||||
|  |                 .unwrap_or(log::LevelFilter::Info), | ||||||
|  |         ) | ||||||
|  |         .chain(std::io::stdout()) | ||||||
|  |         .apply() | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								sync-runner/src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								sync-runner/src/main.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | ||||||
|  | use std::{ | ||||||
|  |     env::set_current_dir, | ||||||
|  |     fs::{exists, read_to_string, File}, | ||||||
|  |     path::{absolute, Path}, | ||||||
|  |     process::{exit, Stdio}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use action::Action; | ||||||
|  | use cfg::Config; | ||||||
|  | use clap::Parser; | ||||||
|  | use colored::Colorize; | ||||||
|  | use execute::{command_args, Execute}; | ||||||
|  | use log::{debug, error, info, trace, warn}; | ||||||
|  | use prelude::abspath; | ||||||
|  | 
 | ||||||
|  | mod action; | ||||||
|  | mod cfg; | ||||||
|  | mod crates; | ||||||
|  | mod logging; | ||||||
|  | mod prelude; | ||||||
|  | mod source; | ||||||
|  | 
 | ||||||
|  | fn main() -> Result<(), Box<dyn std::error::Error>> { | ||||||
|  |     logging::setup_logger()?; | ||||||
|  | 
 | ||||||
|  |     let git_sha1 = String::from_utf8( | ||||||
|  |         command_args!("git", "rev-parse", "HEAD") | ||||||
|  |             .stdout(Stdio::piped()) | ||||||
|  |             .execute_output()? | ||||||
|  |             .stdout, | ||||||
|  |     )?; | ||||||
|  | 
 | ||||||
|  |     let action = Action::parse(); | ||||||
|  |     match action { | ||||||
|  |         Action::Sync { config_path } => { | ||||||
|  |             trace!("fetching config dir... {config_path:?}"); | ||||||
|  |             if let Some(config_path) = abspath(&config_path.unwrap_or("~/.syncr".into())) { | ||||||
|  |                 trace!("setting config dir as cwd... {config_path}"); | ||||||
|  |                 set_current_dir(config_path)?; | ||||||
|  |             } | ||||||
|  |             let config = | ||||||
|  |                 toml::from_str::<Config>(&read_to_string(abspath("./syncr.toml").unwrap())?)?; | ||||||
|  |             info!("syncing \"{}\"...", config.title.bold()); | ||||||
|  | 
 | ||||||
|  |             info!("updating sources..."); | ||||||
|  |             let mut available_sources = vec![]; | ||||||
|  |             for (name, source) in &config.source { | ||||||
|  |                 debug!("checking {name}..."); | ||||||
|  |                 if !source.available() { | ||||||
|  |                     warn!("source \"{name}\" unavailable."); | ||||||
|  |                 } else { | ||||||
|  |                     info!("source \"{name}\" available!"); | ||||||
|  |                     available_sources.push(source); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if available_sources.len() == 0 { | ||||||
|  |                 error!("{}", "sync impossible; no sources.".bold()); | ||||||
|  |                 exit(1); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             let oldpwd = absolute(".")?; | ||||||
|  |             for source in available_sources { | ||||||
|  |                 // cd to source dir
 | ||||||
|  |                 source.go_to_dir()?; | ||||||
|  |                 for c in source.get_crates()? { | ||||||
|  |                     info!("{} pkgs", c.pkgs.len()) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         _ => { | ||||||
|  |             println!("{action:#?}"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								sync-runner/src/prelude.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								sync-runner/src/prelude.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | pub fn abspath(p: &str) -> Option<String> { | ||||||
|  |     let exp_path = shellexpand::full(p).ok()?; | ||||||
|  |     let can_path = std::fs::canonicalize(exp_path.as_ref()).ok()?; | ||||||
|  |     can_path.into_os_string().into_string().ok() | ||||||
|  | } | ||||||
							
								
								
									
										241
									
								
								sync-runner/src/source/git.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								sync-runner/src/source/git.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,241 @@ | ||||||
|  | use std::{ | ||||||
|  |     env::current_dir, fs::{self, create_dir_all, exists}, io::Write, path::{Path, PathBuf} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use git2::Repository; | ||||||
|  | use log::{debug, info, trace, warn}; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | use sha2::{Digest, Sha256, Sha512}; | ||||||
|  | 
 | ||||||
|  | use crate::prelude::abspath; | ||||||
|  | 
 | ||||||
|  | #[derive(Serialize, Deserialize, Debug)] | ||||||
|  | pub struct Git { | ||||||
|  |     pub url: String, | ||||||
|  |     #[serde(default = "default_branch")] | ||||||
|  |     pub branch: String, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn default_branch() -> String { | ||||||
|  |     "main".to_string() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Git { | ||||||
|  |     fn url_hash(&self) -> String { | ||||||
|  |         let mut hasher = Sha256::new(); | ||||||
|  |         hasher.update(&self.url); | ||||||
|  |         let hash = hasher.finalize(); | ||||||
|  |         hex::encode(hash) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn branch_hash(&self) -> String { | ||||||
|  |         let mut hasher = Sha256::new(); | ||||||
|  |         hasher.update(&self.url); | ||||||
|  |         let hash = hasher.finalize(); | ||||||
|  |         hex::encode(hash) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn repository_path_str(&self) -> String { | ||||||
|  |         format!(".data/git/{}{}", self.url_hash(), self.branch_hash()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn repository_path(&self) -> Result<PathBuf, std::io::Error> { | ||||||
|  |         fs::canonicalize(self.repository_path_str()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn exists_on_fs(&self) -> bool { | ||||||
|  |         self.repository_path().is_ok() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn clone_repository(&self) -> Result<Repository, git2::Error> { | ||||||
|  |         Repository::clone_recurse(&self.url, Path::new(&self.repository_path_str())) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn repository(&self) -> Result<Repository, git2::Error> { | ||||||
|  |         if !self.exists_on_fs() { | ||||||
|  |             create_dir_all(self.repository_path_str()).unwrap(); | ||||||
|  |         } | ||||||
|  |         match Repository::open(self.repository_path().unwrap()) { | ||||||
|  |             Ok(r) => Ok(r), | ||||||
|  |             Err(_) => self.clone_repository(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn up_to_date(&self) -> Result<bool, Box<dyn std::error::Error>>{ | ||||||
|  |         debug!("checking repo up to date..."); | ||||||
|  |         let repo = self.repository()?; | ||||||
|  |         let mut remote = repo.find_remote("origin")?; | ||||||
|  | 
 | ||||||
|  |         // Fetch latest references from remote
 | ||||||
|  |         remote.fetch(&[self.branch.clone()], None, None)?; | ||||||
|  | 
 | ||||||
|  |         let fetch_head = repo.refname_to_id(&format!("refs/remotes/origin/{}", self.branch))?; | ||||||
|  |         let local_head = repo.refname_to_id(&format!("refs/heads/{}", self.branch))?; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         Ok(fetch_head == local_head) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn update(&self) -> Result<bool, Box<dyn std::error::Error>> { | ||||||
|  |         if self.up_to_date()? { | ||||||
|  |             return Ok(true); | ||||||
|  |         } | ||||||
|  |         debug!("updating repository..."); | ||||||
|  |         let repository = self.repository()?; | ||||||
|  |         let mut remote = repository.find_remote("origin")?; | ||||||
|  |         let mut cb = git2::RemoteCallbacks::new(); | ||||||
|  | 
 | ||||||
|  |         cb.transfer_progress(|stats| { | ||||||
|  |             if stats.received_objects() == stats.total_objects() { | ||||||
|  |                 print!( | ||||||
|  |                     "resolving deltas {}/{}\r", | ||||||
|  |                     stats.indexed_deltas(), | ||||||
|  |                     stats.total_deltas() | ||||||
|  |                 ); | ||||||
|  |             } else if stats.total_objects() > 0 { | ||||||
|  |                 print!( | ||||||
|  |                     "received {}/{} objects ({}) in {} bytes\r", | ||||||
|  |                     stats.received_objects(), | ||||||
|  |                     stats.total_objects(), | ||||||
|  |                     stats.indexed_objects(), | ||||||
|  |                     stats.received_bytes() | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |             std::io::stdout().flush().unwrap(); | ||||||
|  |             true | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         let mut fo = git2::FetchOptions::new(); | ||||||
|  |         fo.remote_callbacks(cb); | ||||||
|  |         // Always fetch all tags.
 | ||||||
|  |         // Perform a download and also update tips
 | ||||||
|  |         fo.download_tags(git2::AutotagOption::All); | ||||||
|  |         info!("fetching {}...", remote.name().unwrap()); | ||||||
|  |         remote.fetch(&[self.branch.clone()], Some(&mut fo), None)?; | ||||||
|  | 
 | ||||||
|  |         let fetch_head = repository.find_reference("FETCH_HEAD")?; | ||||||
|  | 
 | ||||||
|  |         do_merge( | ||||||
|  |             &repository, | ||||||
|  |             &self.branch, | ||||||
|  |             repository.reference_to_annotated_commit(&fetch_head)?, | ||||||
|  |         )?; | ||||||
|  | 
 | ||||||
|  |         Ok(true) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn ensure(&self) -> Result<&Self, Box<dyn std::error::Error>> { | ||||||
|  |         if self.exists_on_fs() { | ||||||
|  |             self.update(); | ||||||
|  |         } else { | ||||||
|  |             self.clone_repository()?; | ||||||
|  |         } | ||||||
|  |         Ok(self) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn do_merge<'a>( | ||||||
|  |     repo: &'a Repository, | ||||||
|  |     remote_branch: &str, | ||||||
|  |     fetch_commit: git2::AnnotatedCommit<'a>, | ||||||
|  | ) -> Result<(), git2::Error> { | ||||||
|  |     // 1. do a merge analysis
 | ||||||
|  |     let analysis = repo.merge_analysis(&[&fetch_commit])?; | ||||||
|  | 
 | ||||||
|  |     // 2. Do the appopriate merge
 | ||||||
|  |     if analysis.0.is_fast_forward() { | ||||||
|  |         info!("doing a fast forward..."); | ||||||
|  |         // do a fast forward
 | ||||||
|  |         let refname = format!("refs/heads/{}", remote_branch); | ||||||
|  |         match repo.find_reference(&refname) { | ||||||
|  |             Ok(mut r) => { | ||||||
|  |                 fast_forward(repo, &mut r, &fetch_commit)?; | ||||||
|  |             } | ||||||
|  |             Err(_) => { | ||||||
|  |                 // The branch doesn't exist so just set the reference to the
 | ||||||
|  |                 // commit directly. Usually this is because you are pulling
 | ||||||
|  |                 // into an empty repository.
 | ||||||
|  |                 repo.reference( | ||||||
|  |                     &refname, | ||||||
|  |                     fetch_commit.id(), | ||||||
|  |                     true, | ||||||
|  |                     &format!("Setting {} to {}", remote_branch, fetch_commit.id()), | ||||||
|  |                 )?; | ||||||
|  |                 repo.set_head(&refname)?; | ||||||
|  |                 repo.checkout_head(Some( | ||||||
|  |                     git2::build::CheckoutBuilder::default() | ||||||
|  |                         .allow_conflicts(true) | ||||||
|  |                         .conflict_style_merge(true) | ||||||
|  |                         .force(), | ||||||
|  |                 ))?; | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |     } else if analysis.0.is_normal() { | ||||||
|  |         // do a normal merge
 | ||||||
|  |         let head_commit = repo.reference_to_annotated_commit(&repo.head()?)?; | ||||||
|  |         normal_merge(&repo, &head_commit, &fetch_commit)?; | ||||||
|  |     } else { | ||||||
|  |         info!("nothing to do..."); | ||||||
|  |     } | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn fast_forward( | ||||||
|  |     repo: &Repository, | ||||||
|  |     lb: &mut git2::Reference, | ||||||
|  |     rc: &git2::AnnotatedCommit, | ||||||
|  | ) -> Result<(), git2::Error> { | ||||||
|  |     let name = match lb.name() { | ||||||
|  |         Some(s) => s.to_string(), | ||||||
|  |         None => String::from_utf8_lossy(lb.name_bytes()).to_string(), | ||||||
|  |     }; | ||||||
|  |     let msg = format!("fast-forward: setting {} to id: {}", name, rc.id()); | ||||||
|  |     info!("{}", msg); | ||||||
|  |     lb.set_target(rc.id(), &msg)?; | ||||||
|  |     repo.set_head(&name)?; | ||||||
|  |     repo.checkout_head(Some( | ||||||
|  |         git2::build::CheckoutBuilder::default() | ||||||
|  |             // For some reason the force is required to make the working directory actually get updated
 | ||||||
|  |             // I suspect we should be adding some logic to handle dirty working directory states
 | ||||||
|  |             // but this is just an example so maybe not.
 | ||||||
|  |             .force(), | ||||||
|  |     ))?; | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn normal_merge( | ||||||
|  |     repo: &Repository, | ||||||
|  |     local: &git2::AnnotatedCommit, | ||||||
|  |     remote: &git2::AnnotatedCommit, | ||||||
|  | ) -> Result<(), git2::Error> { | ||||||
|  |     let local_tree = repo.find_commit(local.id())?.tree()?; | ||||||
|  |     let remote_tree = repo.find_commit(remote.id())?.tree()?; | ||||||
|  |     let ancestor = repo | ||||||
|  |         .find_commit(repo.merge_base(local.id(), remote.id())?)? | ||||||
|  |         .tree()?; | ||||||
|  |     let mut idx = repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?; | ||||||
|  | 
 | ||||||
|  |     if idx.has_conflicts() { | ||||||
|  |         warn!("merge conficts detected..."); | ||||||
|  |         repo.checkout_index(Some(&mut idx), None)?; | ||||||
|  |         return Ok(()); | ||||||
|  |     } | ||||||
|  |     let result_tree = repo.find_tree(idx.write_tree_to(repo)?)?; | ||||||
|  |     // now create the merge commit
 | ||||||
|  |     let msg = format!("Merge: {} into {}", remote.id(), local.id()); | ||||||
|  |     let sig = repo.signature()?; | ||||||
|  |     let local_commit = repo.find_commit(local.id())?; | ||||||
|  |     let remote_commit = repo.find_commit(remote.id())?; | ||||||
|  |     // Do our merge commit and set current branch head to that commit.
 | ||||||
|  |     let _merge_commit = repo.commit( | ||||||
|  |         Some("HEAD"), | ||||||
|  |         &sig, | ||||||
|  |         &sig, | ||||||
|  |         &msg, | ||||||
|  |         &result_tree, | ||||||
|  |         &[&local_commit, &remote_commit], | ||||||
|  |     )?; | ||||||
|  |     // Set working tree to match head.
 | ||||||
|  |     repo.checkout_head(None)?; | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								sync-runner/src/source/mod.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								sync-runner/src/source/mod.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | ||||||
|  | use std::{env::{current_dir, set_current_dir}, fs::{create_dir_all, read_to_string}, path::PathBuf}; | ||||||
|  | 
 | ||||||
|  | use log::{debug, info, trace}; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | 
 | ||||||
|  | use crate::{crates::Crate, prelude::abspath}; | ||||||
|  | 
 | ||||||
|  | pub mod git; | ||||||
|  | 
 | ||||||
|  | #[derive(Serialize, Deserialize, Debug)] | ||||||
|  | #[serde(default)] | ||||||
|  | pub struct Source { | ||||||
|  |     interval: u64, | ||||||
|  |     git: Option<git::Git>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Default for Source { | ||||||
|  |     fn default() -> Self { | ||||||
|  |         Source { | ||||||
|  |             interval: 60, | ||||||
|  |             git: None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Source { | ||||||
|  |     pub fn available(&self) -> bool { | ||||||
|  |         if let Some(git) = &self.git { | ||||||
|  |             trace!("checking git..."); | ||||||
|  |             return git.ensure().is_ok(); | ||||||
|  |         } | ||||||
|  |         false | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn go_to_dir(&self) -> Result<(), Box<dyn std::error::Error>> { | ||||||
|  |         if let Some(git) = &self.git { | ||||||
|  |             if PathBuf::from(git.repository_path_str()) == current_dir()? { | ||||||
|  |                 return Ok(()) | ||||||
|  |             } | ||||||
|  |             let dir = git.ensure()?.repository_path()?; | ||||||
|  |             trace!("setting git dir as cwd... ({}@{}, {})", git.url, git.branch, dir.display()); | ||||||
|  |             set_current_dir(dir)?; | ||||||
|  |         } | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_crates(&self) -> Result<Vec<Crate>, Box<dyn std::error::Error>> { | ||||||
|  |         let mut crates = vec![]; | ||||||
|  |         if let Some(git) = &self.git { | ||||||
|  |             trace!("getting crates from git..."); | ||||||
|  |             debug!("{}", current_dir()?.display()); | ||||||
|  | 
 | ||||||
|  |             // get crates (read dir, crates/*/crate.toml)
 | ||||||
|  |             for crate_file in glob::glob("crates/*/crate.toml").expect("err") { | ||||||
|  |                 debug!("{crate_file:#?}"); | ||||||
|  |                 match crate_file { | ||||||
|  |                     Ok(cd) =>{ 
 | ||||||
|  |                         debug!("{}", cd.display()); | ||||||
|  |                         crates.push(toml::from_str(&read_to_string(cd)?)?) | ||||||
|  |                     }, | ||||||
|  |                     _ => continue
 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         debug!("{:#?}", crates); | ||||||
|  |         Ok(crates) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								sync.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								sync.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | node sync-runner/index.js | ||||||
							
								
								
									
										17
									
								
								syncr.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								syncr.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | title = "strix's syncr config" | ||||||
|  | 
 | ||||||
|  | [daemon] | ||||||
|  | # interval | ||||||
|  | # discription: how often to check for new updates, this is the default for syncs | ||||||
|  | #              you can define a custom interval for specific sources | ||||||
|  | # unit = minutes | ||||||
|  | interval = 60 | ||||||
|  | 
 | ||||||
|  | [source.personal.git] # default is the uid | ||||||
|  | url = "https://git.saluco.nl/strix/dotfiles.git" | ||||||
|  | crate_dir = "./crates"                           # default | ||||||
|  | cfg_toml = "./syncr.toml"                        # default | ||||||
|  | 
 | ||||||
|  | [source.work.git] | ||||||
|  | url = "https://git.saluco.nl/dotfiles.git" | ||||||
|  | branch = "work" | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue