Skip to content

Commit

Permalink
Implement most of diff
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpurkhiser committed Jul 12, 2019
1 parent 2126a08 commit e250993
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 25 deletions.
40 changes: 30 additions & 10 deletions cmd/dots/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"

"go.evanpurkhiser.com/dots/installer"
"go.evanpurkhiser.com/dots/resolver"

"github.com/spf13/cobra"
)

Expand All @@ -29,26 +34,41 @@ var diffCmd = cobra.Command{

sourceTmp, err := ioutil.TempDir("", "dots-source")
if err != nil {
return fmt.Errorf("Failed to create tmp directory: %s\n", err)
return fmt.Errorf("failed to create tmp directory: %s", err)
}
defer os.RemoveAll(sourceTmp)

activeTmp, err := ioutil.TempDir("", "dots-active")
if err != nil {
return fmt.Errorf("Failed to create tmp directory: %s\n", err)
// Create a "pretty link" so that our diff looks nicer
prettyLink := sourceConfig.InstallPath + "-staged"
if err := os.Symlink(sourceTmp, prettyLink); err != nil {
return fmt.Errorf("failed to create tmp symlink: %s", err)
}
defer os.Remove(prettyLink)

installConfig := installer.InstallConfig{
SourceConfig: sourceConfig,
OverrideInstallPath: sourceTmp,
SkipInstallScripts: true,
}

dotfiles := resolver.ResolveDotfiles(*sourceConfig, *sourceLockfile)
prepared := installer.PrepareDotfiles(dotfiles.Filter(files), *sourceConfig)
installer.InstallDotfiles(prepared, installConfig)

fmt.Println(sourceTmp, activeTmp)
git := []string{"diff", "--no-index", "--diff-filter=MA"}
git = append(git, flags...)
git = append(git, "--", sourceConfig.InstallPath, prettyLink+"/")

exec := []string{"git", "diff", "--no-index"}
exec = append(exec, flags...)
exec = append(exec, "--", sourceTmp, activeTmp)
command := exec.Command("git", git...)
command.Stdout = os.Stdout
command.Stderr = os.Stderr

fmt.Println(exec)
command.Run()

return nil
},

Args: cobra.ArbitraryArgs,
Args: cobra.ArbitraryArgs,
DisableFlagsInUseLine: true,
DisableFlagParsing: true,
}
56 changes: 49 additions & 7 deletions installer/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sync"

"go.evanpurkhiser.com/dots/config"
"go.evanpurkhiser.com/dots/resolver"
)

const separator = string(os.PathSeparator)
Expand All @@ -23,8 +24,30 @@ type InstallConfig struct {
// OverrideInstallPath specifies a path to install the dotfile at,
// overriding the configuration in the SourceConfig.
OverrideInstallPath string

// ForceReinstall installs the dotfile even if the dotfile has not been
// changed from its source. This implies that install scripts will be run.
ForceReinstall bool

// SkipInstallScripts disables execution of any triggered install scripts
SkipInstallScripts bool

// TODO We can probably add a channel here to pipe logging output so that we
// can output some logging
}

// InstalledDotfile is a represents of the dotfile *after* it has been
// installed into the configuration directory.
type InstalledDotfile struct {
*PreparedDotfile

// InstallError represents an error that occurred during installation.
InstallError error
}

// InstallDotfile is given a prepared dotfile and installation configuration
// and will perform all the necessary actions to install the file into it's
// target location.
func InstallDotfile(dotfile *PreparedDotfile, config InstallConfig) error {
installPath := config.SourceConfig.InstallPath + separator + dotfile.Path

Expand All @@ -36,7 +59,7 @@ func InstallDotfile(dotfile *PreparedDotfile, config InstallConfig) error {
return fmt.Errorf("Source files are not all regular files")
}

if !dotfile.IsChanged() {
if !dotfile.IsChanged() && !config.ForceReinstall {
return nil
}

Expand Down Expand Up @@ -79,23 +102,42 @@ func InstallDotfile(dotfile *PreparedDotfile, config InstallConfig) error {
return err
}

func InstallDotfiles(dotfiles PreparedDotfiles, config InstallConfig) []error {
// RunInstallScripts executes all install scripts for a single dotfile.
func RunInstallScripts(dotfile resolver.Dotfile, config InstallConfig) error {
// TODO actually implement this
fmt.Println(dotfile.InstallScripts)

return nil
}

// InstalledDotfiles asynchronously calls InstalledDotfile on all passed
// PreparedDotfiles. Once all dotfiles have been installed, all install scripts
// will execute, in order of installation (unless SkipInstallScripts is on).
func InstallDotfiles(dotfiles PreparedDotfiles, config InstallConfig) []*InstalledDotfile {
waitGroup := sync.WaitGroup{}
waitGroup.Add(len(dotfiles))

errors := []error{}
installed := make([]*InstalledDotfile, len(dotfiles))

for _, dotfile := range dotfiles {
for i, dotfile := range dotfiles {
go func(dotfile *PreparedDotfile) {
err := InstallDotfile(dotfile, config)
if err != nil {
errors = append(errors, err)
installed[i] = &InstalledDotfile{
PreparedDotfile: dotfile,
InstallError: err,
}
waitGroup.Done()
}(dotfile)
}

waitGroup.Wait()

return errors
// Nothing left to do if there are no install scripts to run
if config.SkipInstallScripts {
return installed
}

// TODO After all dotfiles are installed, we now must run our installation scripts

return installed
}
16 changes: 8 additions & 8 deletions resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ type Dotfile struct {
// Sources is the set of SourceFiles
Sources []*SourceFile

// Install files is the list of installation scripts that will be executed
// InstallScripts is the list of installation scripts that will be executed
// when the dotfile has been installed or modified.
InstallFiles []string
InstallScripts []string
}

// Dotfiles holds a list of Dotfiles.
Expand Down Expand Up @@ -200,10 +200,10 @@ func resolveOverrides(dotfiles dotfileMap, overrideSuffix string) {
}
}

// resolveInstalls looks for dotfiles ending in the installSuffix and will map
// them to the dorfile they are named after, or any dotfile's that exist within
// resolveInstallScripts looks for dotfiles ending in the installSuffix and will map
// them to the dotfile they are named after, or any dotfile's that exist within
// the directory they are named after.
func resolveInstalls(dotfiles dotfileMap, installSuffix string) {
func resolveInstallScripts(dotfiles dotfileMap, installSuffix string) {
for path, dotfile := range dotfiles {
if strings.HasSuffix(path, installSuffix) {
continue
Expand All @@ -222,7 +222,7 @@ func resolveInstalls(dotfiles dotfileMap, installSuffix string) {
}

for _, installSource := range installFile.Sources {
dotfile.InstallFiles = append(dotfile.InstallFiles, installSource.Path)
dotfile.InstallScripts = append(dotfile.InstallScripts, installSource.Path)
}
}
}
Expand Down Expand Up @@ -292,9 +292,9 @@ func ResolveDotfiles(conf config.SourceConfig, lockfile config.SourceLockfile) D
resolveOverrides(dotfiles, "."+conf.OverrideSuffix)
}

// Install files and removed files can be computed after all dotfiles have
// Install scripts and removed files can be computed after all dotfiles have
// been cascaded together
resolveInstalls(dotfiles, "."+conf.InstallSuffix)
resolveInstallScripts(dotfiles, "."+conf.InstallSuffix)
resolveRemoved(dotfiles, lockfile.InstalledFiles)

// Mark dotfiles which will have environment expansion
Expand Down

0 comments on commit e250993

Please sign in to comment.