feat: add --dry-run flag (#6)
* feat: add --dry-run flag to all commands * feat: update copy-go with single copy.Replace * refactor: make Config interface * chore(config): cleanup unused * feat: add config demo (1/?) * chore: better naming for cfg * refactor: move to pkg config * refactor: use data for store configs * refactor: split real and demo config * feat: make use of dry run flag Co-authored-by: Tran Hau <ngtranhau@gmail.com>main
parent
ecafc5b74d
commit
4fa12066d0
|
@ -1,13 +0,0 @@
|
|||
import:
|
||||
- ~/.config/alacritty/one-dark.yml
|
||||
|
||||
font:
|
||||
normal:
|
||||
family: Cascadia Code
|
||||
style: Regular
|
||||
|
||||
bold:
|
||||
family: Cascadia Code
|
||||
style: Bold
|
||||
|
||||
size: 12
|
|
@ -1,21 +0,0 @@
|
|||
# https://github.com/alacritty/alacritty/wiki/Color-schemes
|
||||
# Colors (One Dark)
|
||||
colors:
|
||||
primary:
|
||||
background: "#282c34"
|
||||
foreground: "#abb2bf"
|
||||
cursor:
|
||||
text: CellBackground
|
||||
cursor: "#528bff"
|
||||
selection:
|
||||
text: CellForeground
|
||||
background: "#3e4451"
|
||||
normal:
|
||||
black: "#5c6370"
|
||||
red: "#e06c75"
|
||||
green: "#98c379"
|
||||
yellow: "#e5c07b"
|
||||
blue: "#61afef"
|
||||
magenta: "#c678dd"
|
||||
cyan: "#56b6c2"
|
||||
white: "#828997"
|
|
@ -1,3 +0,0 @@
|
|||
--theme="TwoDark"
|
||||
|
||||
--style="plain"
|
|
@ -1,88 +0,0 @@
|
|||
{
|
||||
"apps": {
|
||||
"nvim": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/nvim/init.vim",
|
||||
"external": "~/.config/nvim/init.vim"
|
||||
}
|
||||
]
|
||||
},
|
||||
"vim": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/vim/vimrc",
|
||||
"external": "~/.vimrc"
|
||||
}
|
||||
]
|
||||
},
|
||||
"bat": {
|
||||
"dirs": [
|
||||
{
|
||||
"internal": "config/bat",
|
||||
"external": "~/.config/bat"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tmux": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/tmux/tmux.conf",
|
||||
"external": "~/.tmux.conf"
|
||||
}
|
||||
]
|
||||
},
|
||||
"alacritty": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/alacritty/alacritty.yml",
|
||||
"external": "~/.config/alacritty/alacritty.yml"
|
||||
},
|
||||
{
|
||||
"internal": "config/alacritty/one-dark.yml",
|
||||
"external": "~/.config/alacritty/one-dark.yml"
|
||||
}
|
||||
]
|
||||
},
|
||||
"i3": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/i3/config",
|
||||
"external": "~/.config/i3/config"
|
||||
}
|
||||
]
|
||||
},
|
||||
"i3status": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/i3status/config",
|
||||
"external": "~/.config/i3status/config"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rofi": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/rofi/config.rasi",
|
||||
"external": "~/.config/rofi/config.rasi"
|
||||
}
|
||||
]
|
||||
},
|
||||
"xinit": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/xinit/xinitrc",
|
||||
"external": "~/.xinitrc"
|
||||
}
|
||||
]
|
||||
},
|
||||
"redshift": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/redshift/redshift.conf",
|
||||
"external": "~/.config/redshift/redshift.conf"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
139
config/i3/config
139
config/i3/config
|
@ -1,139 +0,0 @@
|
|||
# https://i3wm.org/docs/userguide.html
|
||||
|
||||
set $mod Mod4
|
||||
|
||||
font pango:Cascadia Code 12
|
||||
|
||||
# feh
|
||||
# https://wiki.archlinux.org/index.php/Feh
|
||||
exec --no-startup-id feh --no-fehbg --bg-fill --randomize /usr/share/backgrounds/archlinux/*
|
||||
|
||||
# redshift
|
||||
# https://wiki.archlinux.org/index.php/Redshift
|
||||
exec --no-startup-id redshift-gtk
|
||||
|
||||
# fcitx
|
||||
# https://wiki.archlinux.org/index.php/fcitx
|
||||
exec --no-startup-id fcitx
|
||||
|
||||
# i3lock
|
||||
bindsym $mod+l exec --no-startup-id i3lock -e -c 000000
|
||||
|
||||
# adjust volume
|
||||
set $refresh_i3status killall -SIGUSR1 i3status
|
||||
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5% && $refresh_i3status
|
||||
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5% && $refresh_i3status
|
||||
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status
|
||||
bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status
|
||||
|
||||
# adjust brightness
|
||||
bindsym XF86MonBrightnessUp exec --no-startup-id xbacklight -inc 10
|
||||
bindsym XF86MonBrightnessDown exec --no-startup-id xbacklight -dec 10
|
||||
|
||||
# use Mouse+$mod to move floating windows
|
||||
floating_modifier $mod
|
||||
|
||||
# start a terminal
|
||||
bindsym $mod+Return exec i3-sensible-terminal
|
||||
|
||||
# kill focused window
|
||||
bindsym $mod+Shift+q kill
|
||||
|
||||
# rofi (a program launcher)
|
||||
# https://wiki.archlinux.org/index.php/Rofi
|
||||
bindsym $mod+d exec "rofi -combi-modi window,drun -show combi"
|
||||
|
||||
# change focus
|
||||
bindsym $mod+Left focus left
|
||||
bindsym $mod+Down focus down
|
||||
bindsym $mod+Up focus up
|
||||
bindsym $mod+Right focus right
|
||||
|
||||
# move focused window
|
||||
bindsym $mod+Shift+Left move left
|
||||
bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Right move right
|
||||
|
||||
# split in horizontal orientation
|
||||
bindsym $mod+h split h
|
||||
|
||||
# split in vertical orientation
|
||||
bindsym $mod+v split v
|
||||
|
||||
# enter fullscreen mode
|
||||
bindsym $mod+f fullscreen toggle
|
||||
|
||||
# change container layout (stacked, tabbed, toggle split)
|
||||
bindsym $mod+s layout stacking
|
||||
bindsym $mod+w layout tabbed
|
||||
bindsym $mod+e layout toggle split
|
||||
|
||||
# toggle tiling / floating
|
||||
bindsym $mod+Shift+space floating toggle
|
||||
|
||||
# change focus between tiling / floating windows
|
||||
bindsym $mod+space focus mode_toggle
|
||||
|
||||
# focus the parent container
|
||||
bindsym $mod+a focus parent
|
||||
|
||||
# workspace
|
||||
set $ws1 "1"
|
||||
set $ws2 "2"
|
||||
set $ws3 "3"
|
||||
set $ws4 "4"
|
||||
set $ws5 "5"
|
||||
set $ws6 "6"
|
||||
set $ws7 "7"
|
||||
set $ws8 "8"
|
||||
set $ws9 "9"
|
||||
set $ws10 "10"
|
||||
|
||||
# switch to workspace
|
||||
bindsym $mod+1 workspace number $ws1
|
||||
bindsym $mod+2 workspace number $ws2
|
||||
bindsym $mod+3 workspace number $ws3
|
||||
bindsym $mod+4 workspace number $ws4
|
||||
bindsym $mod+5 workspace number $ws5
|
||||
bindsym $mod+6 workspace number $ws6
|
||||
bindsym $mod+7 workspace number $ws7
|
||||
bindsym $mod+8 workspace number $ws8
|
||||
bindsym $mod+9 workspace number $ws9
|
||||
bindsym $mod+0 workspace number $ws10
|
||||
|
||||
# move focused container to workspace
|
||||
bindsym $mod+Shift+1 move container to workspace number $ws1
|
||||
bindsym $mod+Shift+2 move container to workspace number $ws2
|
||||
bindsym $mod+Shift+3 move container to workspace number $ws3
|
||||
bindsym $mod+Shift+4 move container to workspace number $ws4
|
||||
bindsym $mod+Shift+5 move container to workspace number $ws5
|
||||
bindsym $mod+Shift+6 move container to workspace number $ws6
|
||||
bindsym $mod+Shift+7 move container to workspace number $ws7
|
||||
bindsym $mod+Shift+8 move container to workspace number $ws8
|
||||
bindsym $mod+Shift+9 move container to workspace number $ws9
|
||||
bindsym $mod+Shift+0 move container to workspace number $ws10
|
||||
|
||||
bindsym $mod+Shift+c reload
|
||||
bindsym $mod+Shift+r restart
|
||||
bindsym $mod+Shift+e exec "i3-nagbar -t warning -f 'pango:Cascadia Code 12' -m 'Do you want to exit i3?' -B 'Yes, exit i3' 'i3-msg exit'"
|
||||
|
||||
# resize window
|
||||
mode "resize" {
|
||||
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+r mode "resize"
|
||||
|
||||
# use i3status
|
||||
bar {
|
||||
position top
|
||||
status_command i3status
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
general {
|
||||
interval = 5
|
||||
|
||||
# https://github.com/joshdick/onedark.vim
|
||||
colors = true
|
||||
color_good = "#98C379"
|
||||
color_degraded = "#E5C07B"
|
||||
color_bad = "#E06C75"
|
||||
}
|
||||
|
||||
order += "wireless _first_"
|
||||
order += "ethernet _first_"
|
||||
order += "battery all"
|
||||
order += "volume master"
|
||||
order += "tztime local"
|
||||
|
||||
wireless _first_ {
|
||||
format_up = "Wifi: %essid"
|
||||
format_down = "Wifi: down"
|
||||
}
|
||||
|
||||
ethernet _first_ {
|
||||
format_up = "Ethernet: %ip (%speed)"
|
||||
format_down = "Ethernet: down"
|
||||
}
|
||||
|
||||
battery all {
|
||||
format = "%status %percentage %remaining"
|
||||
}
|
||||
|
||||
volume master {
|
||||
format = "Sound: %volume"
|
||||
format_muted = "Sound: muted (%volume)"
|
||||
device = "pulse"
|
||||
}
|
||||
|
||||
tztime local {
|
||||
format = "%Y-%m-%d %H:%M:%S"
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
[redshift]
|
||||
location-provider=manual
|
||||
|
||||
[manual]
|
||||
; Ho Chi Minh, Vietnam
|
||||
lat=10.8188
|
||||
lon=106.65186
|
|
@ -1,4 +0,0 @@
|
|||
configuration {
|
||||
modi: "window,drun,combi";
|
||||
font: "Cascadia Code 12";
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
# https://github.com/tmux/tmux/wiki/FAQ
|
||||
|
||||
# Switch panes using Alt without prefix
|
||||
bind -n M-Left select-pane -L
|
||||
bind -n M-Right select-pane -R
|
||||
bind -n M-Up select-pane -U
|
||||
bind -n M-Down select-pane -D
|
||||
|
||||
# Color
|
||||
set -g default-terminal "tmux-256color"
|
||||
|
||||
# https://github.com/tmux-plugins/tpm
|
||||
# List of plugins
|
||||
set -g @plugin 'tmux-plugins/tpm'
|
||||
set -g @plugin 'tmux-plugins/tmux-sensible'
|
||||
set -g @plugin 'tmux-plugins/tmux-pain-control'
|
||||
|
||||
# Initialize TMUX plugin manager
|
||||
run '~/.tmux/plugins/tpm/tpm'
|
|
@ -1,52 +0,0 @@
|
|||
set breakindent
|
||||
set completeopt=menuone,noinsert,noselect
|
||||
set noswapfile
|
||||
set number
|
||||
set relativenumber
|
||||
set scrolloff=4
|
||||
set virtualedit=block
|
||||
set whichwrap=<,>,[,]
|
||||
|
||||
" True color
|
||||
" https://gist.github.com/XVilka/8346728
|
||||
if (empty($TMUX))
|
||||
if (has('termguicolors'))
|
||||
set termguicolors
|
||||
endif
|
||||
endif
|
||||
|
||||
" Disable cursor styling
|
||||
set guicursor=
|
||||
|
||||
" Install xclip or xsel
|
||||
set clipboard+=unnamedplus
|
||||
|
||||
" FZF
|
||||
set rtp+=~/.fzf
|
||||
|
||||
" Plugins config
|
||||
let g:go_fmt_command='gopls'
|
||||
let g:go_gopls_gofumpt=1
|
||||
let g:go_version_warning=0
|
||||
let g:lightline={'colorscheme':'onedark'}
|
||||
|
||||
" vim-plug
|
||||
" https://github.com/junegunn/vim-plug
|
||||
call plug#begin()
|
||||
|
||||
" Should use
|
||||
Plug 'sheerun/vim-polyglot'
|
||||
Plug 'preservim/nerdtree'
|
||||
Plug 'machakann/vim-sandwich'
|
||||
Plug 'itchyny/lightline.vim'
|
||||
|
||||
" Colorschemes
|
||||
Plug 'joshdick/onedark.vim'
|
||||
|
||||
" Languages
|
||||
Plug 'fatih/vim-go', {'tag': '*'}
|
||||
|
||||
call plug#end()
|
||||
|
||||
set background=dark
|
||||
colorscheme onedark
|
|
@ -1,7 +0,0 @@
|
|||
# https://wiki.archlinux.org/index.php/fcitx
|
||||
export GTK_IM_MODULE=fcitx
|
||||
export QT_IM_MODULE=fcitx
|
||||
export XMODIFIERS=@im=fcitx
|
||||
|
||||
# https://wiki.archlinux.org/index.php/i3
|
||||
exec i3
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"apps": {
|
||||
"nvim": {
|
||||
"files": [
|
||||
{
|
||||
"internal": "config/nvim/init.vim",
|
||||
"external": "~/.config/nvim/init.vim"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
62
file.go
62
file.go
|
@ -1,62 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
|
||||
copier "github.com/haunt98/copy-go"
|
||||
)
|
||||
|
||||
const (
|
||||
homeSymbol = '~'
|
||||
)
|
||||
|
||||
type copyFn func(from, to string) error
|
||||
|
||||
func replaceFile(from, to string) error {
|
||||
return replace(from, to, copier.CopyFile)
|
||||
}
|
||||
|
||||
func replaceDir(from, to string) error {
|
||||
return replace(from, to, copier.CopyDir)
|
||||
}
|
||||
|
||||
func replace(from, to string, fn copyFn) error {
|
||||
newFrom, err := replaceHomeSymbol(from)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to replace home symbol %s: %w", from, err)
|
||||
}
|
||||
|
||||
newTo, err := replaceHomeSymbol(to)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to replace home symbol %s: %w", to, err)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(newTo); err != nil {
|
||||
return fmt.Errorf("failed to remove %s: %w", newTo, err)
|
||||
}
|
||||
|
||||
if err := fn(newFrom, newTo); err != nil {
|
||||
return fmt.Errorf("failed to copy from %s to %s: %w", newFrom, newTo, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// replace ~
|
||||
// https://stackoverflow.com/a/17609894
|
||||
func replaceHomeSymbol(path string) (string, error) {
|
||||
if path == "" || path[0] != homeSymbol {
|
||||
return path, nil
|
||||
}
|
||||
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
newPath := filepath.Join(currentUser.HomeDir, path[1:])
|
||||
return newPath, nil
|
||||
}
|
2
go.mod
2
go.mod
|
@ -5,7 +5,7 @@ go 1.16
|
|||
require (
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/haunt98/color v0.1.0
|
||||
github.com/haunt98/copy-go v0.4.0
|
||||
github.com/haunt98/copy-go v0.5.0
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -6,8 +6,8 @@ github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
|||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/haunt98/color v0.1.0 h1:qfP5oNI3aoUC8T+bH/JNVAg79ljyhTGpgfqSKWhkiQQ=
|
||||
github.com/haunt98/color v0.1.0/go.mod h1:V4BPVUSuiOItuVZHRHUTkpxO7OYQiP0DSgIWMpC/2qs=
|
||||
github.com/haunt98/copy-go v0.4.0 h1:ts47dExLyIWWrnLQmVc475Af3/LO111zeB58waSe02A=
|
||||
github.com/haunt98/copy-go v0.4.0/go.mod h1:cK1mRlW7QXPHhe5YI1VtL/U4OjUbRLAtZnO/oucrwRI=
|
||||
github.com/haunt98/copy-go v0.5.0 h1:8yy7Dx47BBtlHIFIXxcCIECZRoQB/JSgLN9yunqtLAQ=
|
||||
github.com/haunt98/copy-go v0.5.0/go.mod h1:cK1mRlW7QXPHhe5YI1VtL/U4OjUbRLAtZnO/oucrwRI=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
|
|
61
main.go
61
main.go
|
@ -7,6 +7,7 @@ import (
|
|||
"runtime"
|
||||
|
||||
"github.com/haunt98/color"
|
||||
"github.com/haunt98/dotfiles/pkg/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
@ -16,6 +17,7 @@ const (
|
|||
|
||||
// flags
|
||||
verboseFlag = "verbose"
|
||||
dryRunFlag = "dry-run"
|
||||
|
||||
// commands
|
||||
installCommand = "install"
|
||||
|
@ -24,6 +26,7 @@ const (
|
|||
|
||||
// usages
|
||||
verboseUsage = "show what is going on"
|
||||
dryRunUsage = "demo mode without actually changing anything"
|
||||
installUsage = "install user configs from dotfiles"
|
||||
updateUsage = "update dotfiles from user configs"
|
||||
cleanUsage = "clean unused dotfiles"
|
||||
|
@ -66,6 +69,10 @@ func main() {
|
|||
Name: verboseFlag,
|
||||
Usage: verboseUsage,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: dryRunFlag,
|
||||
Usage: dryRunUsage,
|
||||
},
|
||||
},
|
||||
Action: a.RunInstall,
|
||||
},
|
||||
|
@ -73,13 +80,33 @@ func main() {
|
|||
Name: updateCommand,
|
||||
Aliases: updateAliases,
|
||||
Usage: updateUsage,
|
||||
Action: a.RunUpdate,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: verboseFlag,
|
||||
Usage: verboseUsage,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: dryRunFlag,
|
||||
Usage: dryRunUsage,
|
||||
},
|
||||
},
|
||||
Action: a.RunUpdate,
|
||||
},
|
||||
{
|
||||
Name: cleanCommand,
|
||||
Aliases: cleanAliases,
|
||||
Usage: cleanUsage,
|
||||
Action: a.RunClean,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: verboseFlag,
|
||||
Usage: verboseUsage,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: dryRunFlag,
|
||||
Usage: dryRunUsage,
|
||||
},
|
||||
},
|
||||
Action: a.RunClean,
|
||||
},
|
||||
},
|
||||
Action: a.RunHelp,
|
||||
|
@ -93,6 +120,7 @@ func main() {
|
|||
type action struct {
|
||||
flags struct {
|
||||
verbose bool
|
||||
dryRun bool
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,11 +133,10 @@ func (a *action) RunInstall(c *cli.Context) error {
|
|||
a.getFlags(c)
|
||||
a.log("start %s\n", installCommand)
|
||||
|
||||
cfg, err := LoadConfig(currentDir)
|
||||
cfg, err := a.loadConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load config: %w", err)
|
||||
return err
|
||||
}
|
||||
a.log("config %+v\n", cfg)
|
||||
|
||||
if err := cfg.Install(); err != nil {
|
||||
return fmt.Errorf("failed to install config: %w", err)
|
||||
|
@ -122,11 +149,10 @@ func (a *action) RunUpdate(c *cli.Context) error {
|
|||
a.getFlags(c)
|
||||
a.log("start %s\n", updateCommand)
|
||||
|
||||
cfg, err := LoadConfig(currentDir)
|
||||
cfg, err := a.loadConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load config: %w", err)
|
||||
return err
|
||||
}
|
||||
a.log("config %+v\n", cfg)
|
||||
|
||||
if err := cfg.Update(); err != nil {
|
||||
return fmt.Errorf("failed to update config: %w", err)
|
||||
|
@ -139,11 +165,10 @@ func (a *action) RunClean(c *cli.Context) error {
|
|||
a.getFlags(c)
|
||||
a.log("start %s\n", cleanCommand)
|
||||
|
||||
cfg, err := LoadConfig(currentDir)
|
||||
cfg, err := a.loadConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load config: %w", err)
|
||||
return err
|
||||
}
|
||||
a.log("config %+v\n", cfg)
|
||||
|
||||
if err := cfg.Clean(); err != nil {
|
||||
return fmt.Errorf("failed to clean config: %w", err)
|
||||
|
@ -152,8 +177,22 @@ func (a *action) RunClean(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *action) loadConfig() (config.Config, error) {
|
||||
cfgReal, cfgDemo, err := config.LoadConfig(currentDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load config: %w", err)
|
||||
}
|
||||
|
||||
if a.flags.dryRun {
|
||||
return cfgDemo, nil
|
||||
}
|
||||
|
||||
return cfgReal, nil
|
||||
}
|
||||
|
||||
func (a *action) getFlags(c *cli.Context) {
|
||||
a.flags.verbose = c.Bool(verboseFlag)
|
||||
a.flags.dryRun = c.Bool(dryRunFlag)
|
||||
}
|
||||
|
||||
func (a *action) log(format string, v ...interface{}) {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package config
|
||||
|
||||
type Config interface {
|
||||
Install() error
|
||||
Update() error
|
||||
Clean() error
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package config
|
||||
|
||||
type configDemo struct {
|
||||
configApps
|
||||
}
|
||||
|
||||
var _ Config = (*configDemo)(nil)
|
||||
|
||||
func (cd *configDemo) Install() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cd *configDemo) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cd *configDemo) Clean() error {
|
||||
return nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -6,18 +6,26 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/haunt98/copy-go"
|
||||
)
|
||||
|
||||
const (
|
||||
configDirPath = "config"
|
||||
configFile = "config.json"
|
||||
configDirPath = "data"
|
||||
configFile = "data.json"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
// Read from file
|
||||
type config struct {
|
||||
configApps
|
||||
}
|
||||
|
||||
var _ Config = (*config)(nil)
|
||||
|
||||
type configApps struct {
|
||||
Apps map[string]App `json:"apps"`
|
||||
}
|
||||
|
||||
// Read from file
|
||||
type App struct {
|
||||
Files []Path `json:"files"`
|
||||
Dirs []Path `json:"dirs"`
|
||||
|
@ -28,39 +36,45 @@ type Path struct {
|
|||
External string `json:"external"`
|
||||
}
|
||||
|
||||
// Load config from file
|
||||
func LoadConfig(path string) (result Config, err error) {
|
||||
// LoadConfig return config, configDemo
|
||||
func LoadConfig(path string) (*config, *configDemo, error) {
|
||||
configPath := getConfigPath(path)
|
||||
bytes, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
err = fmt.Errorf("file not exist %s: %w", configPath, err)
|
||||
return
|
||||
return nil, nil, fmt.Errorf("file not exist %s: %w", configPath, err)
|
||||
}
|
||||
|
||||
err = fmt.Errorf("failed to read file%s: %w", configPath, err)
|
||||
return
|
||||
return nil, nil, fmt.Errorf("failed to read file%s: %w", configPath, err)
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(bytes, &result); err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal: %w", err)
|
||||
return
|
||||
var cfgApps configApps
|
||||
if err = json.Unmarshal(bytes, &cfgApps); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to unmarshal: %w", err)
|
||||
}
|
||||
|
||||
return
|
||||
cfg := config{
|
||||
configApps: cfgApps,
|
||||
}
|
||||
|
||||
cfgDemo := configDemo{
|
||||
configApps: cfgApps,
|
||||
}
|
||||
|
||||
return &cfg, &cfgDemo, nil
|
||||
}
|
||||
|
||||
// internal -> external
|
||||
func (c *Config) Install() error {
|
||||
func (c *config) Install() error {
|
||||
for _, app := range c.Apps {
|
||||
for _, file := range app.Files {
|
||||
if err := replaceFile(file.Internal, file.External); err != nil {
|
||||
if err := copy.Replace(file.Internal, file.External); err != nil {
|
||||
return fmt.Errorf("failed to remove and copy from %s to %s: %w", file.Internal, file.External, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, dir := range app.Dirs {
|
||||
if err := replaceDir(dir.Internal, dir.External); err != nil {
|
||||
if err := copy.Replace(dir.Internal, dir.External); err != nil {
|
||||
return fmt.Errorf("failed to remove and copy from %s to %s: %w", dir.Internal, dir.External, err)
|
||||
}
|
||||
}
|
||||
|
@ -70,16 +84,16 @@ func (c *Config) Install() error {
|
|||
}
|
||||
|
||||
// external -> internal
|
||||
func (c *Config) Update() error {
|
||||
func (c *config) Update() error {
|
||||
for _, app := range c.Apps {
|
||||
for _, file := range app.Files {
|
||||
if err := replaceFile(file.External, file.Internal); err != nil {
|
||||
if err := copy.Replace(file.External, file.Internal); err != nil {
|
||||
return fmt.Errorf("failed to remove and copy from %s to %s: %w", file.External, file.Internal, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, dir := range app.Dirs {
|
||||
if err := replaceDir(dir.External, dir.Internal); err != nil {
|
||||
if err := copy.Replace(dir.External, dir.Internal); err != nil {
|
||||
return fmt.Errorf("failed to remove and copy from %s to %s: %w", dir.External, dir.Internal, err)
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +102,7 @@ func (c *Config) Update() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) Clean() error {
|
||||
func (c *config) Clean() error {
|
||||
files, err := os.ReadDir(configDirPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read dir %s: %w", configDirPath, err)
|
Loading…
Reference in New Issue