diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c299a0e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,34 @@ +name: goreleaser + +on: + push: + tags: + - '*' + +permissions: + contents: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - + name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - + name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + with: + distribution: goreleaser + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} + HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..36482ef --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,14 @@ +on: [push, pull_request] +name: Test +jobs: + test: + runs-on: macos-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + - name: Checkout code + uses: actions/checkout@v2 + - name: Test + run: go test ./... diff --git a/.goreleaser.yml b/.goreleaser.yml index b684174..020fc09 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -73,3 +73,4 @@ brews: install: | bin.install "heptapod" + bin.install Dir["rules/*"] diff --git a/README.md b/README.md index 0ae6d96..4c11f38 100644 --- a/README.md +++ b/README.md @@ -3,41 +3,68 @@ This is a command line application to manage and fine-tune [Time Machine](https://support.apple.com/en-us/HT201250) exclude paths. -## This repository is a WIP! The advertised functionality is nonexistent yet :( +
+ Why it is named after creatures from Arrival? +Heptapods are extraterrestrial species from the movie Arrival. +They are special because they have non-linear time perspective. +Their written language (Heptapod B) is basically describes +the future and the past in the same time. Hence the name of the tool. +
-### Repo state -done: - - architecture the protocol/configs - - most of asimovs features are ported - - example rules added - - command line interface - - option to dryrun, show inner states, write to file - - purge option - - we should write down what paths excluded by us, and include them back +### Install -todos: - - handle global deps (m2, ivy, nvm, npm) - - support tmignore functionality - - support tmignore like funcionality with dockerignore - - regexp pattern - - brew package - - ghactions - - hook to rerun periodically/before tmbackups - - port asimov's issues (spotify, spotlight) - - docker support (at least tell if docker vm is persisted or not) - - this is kinda easy with tmutil.GetExcludeList() - - android vms? - - this should be also easy - - preemptive search that tells you how many files with which size will be excluded/included - - nice to have, we can tell the sizes, but counting files need to actually count the files which could be slow AH - - speedtest it - - modify the backup intervals and frequencies - - not sure it can be done with tmutil, but there are applications for this - - probably adding `.` and `..` will break the execution shortcuts and need to fix them - - wildcards like `*.sh` not working right now, do we want to make them work? +```sh +brew tap tg44/heptapod +``` +```sh +brew install heptapod +``` + +### Usage + +``` +heptapod -h +heptapod -h +``` +Will print help! + +``` +heptapod initRules +``` +This will move the currently added ruleset to `~/.heptapod/rules` (or the set `--rules dir` directory) they are added as enabled rules! + +``` +heptapod ls -a +``` +Lists all the rules (you get 4 tables, enabled, disabled, parseable but unrunable and unparsable). + +``` +heptapod lse +``` +Could list all the currently excluded TM paths. + +``` +heptapod -v run -d +``` +Will dryrun the current rules, will log speed informations. (Potentially list nonexistent directories and files!) + +``` +heptapod run +``` +Will run the current rules, and add them to the TM exclude list. Also writes exclude logs to `~/.heptapod/logs` (or the given `--logDir dir`) for easier revert. + +``` +heptapod prune -a +``` +Will revert all the previously added paths from the run-exclude-logs. (`prune -h` could tell you the other useful revert options). -### Notes for migrating to a new machine -`xcode-select --install` may be needed after a migration + + + +### Notes for TM migrating to a new machine +When you try to migrate your TM state to a new machine +`xcode-select --install` may be needed. Somehow this is +sometimes not migrating as you thought it will. ### Rules Every rule has a searchPaths, ignorePaths. @@ -73,3 +100,38 @@ Ignores files/dirs based on other files existence, made for easy language dep ig - [tmignore](https://github.com/samuelmeuli/tmignore) - [various stack exchange responses](https://superuser.com/questions/1161038/exclude-folders-by-regex-from-time-machine-backup) - [tmutil](https://ss64.com/osx/tmutil.html) + +### Contribution +If you are interested in this repo, star it, and write an issue, and we can talk about future ideas there! + + +### Repo/developement state +done: +- architecture the protocol/configs +- most of asimov's features are ported +- example rules added +- command line interface +- option to dryrun, show inner states, write to file +- purge option + - we should write down what paths excluded by us, and include them back +- brew package +- ghactions + +todos: +- handle global deps (m2, ivy, nvm, npm) +- support tmignore functionality +- support tmignore like funcionality with dockerignore +- regexp pattern +- hook to rerun periodically/before tmbackups +- port asimov's issues (spotify, spotlight) +- docker support (at least tell if docker vm is persisted or not) + - this is kinda easy with tmutil.GetExcludeList() +- android vms? + - this should be also easy +- preemptive search that tells you how many files with which size will be excluded/included + - nice to have, we can tell the sizes, but counting files need to actually count the files which could be slow AH +- speedtest it +- modify the backup intervals and frequencies + - not sure it can be done with tmutil, but there are applications for this +- probably adding `.` and `..` will break the execution shortcuts and need to fix them +- wildcards like `*.sh` not working right now, do we want to make them work? diff --git a/go.mod b/go.mod index 5cc54d6..3333cca 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,16 @@ module github.com/tg44/heptapod -go 1.13 +go 1.17 require ( github.com/olekukonko/tablewriter v0.0.5 github.com/urfave/cli/v2 v2.3.0 gopkg.in/yaml.v2 v2.4.0 ) + +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/russross/blackfriday/v2 v2.0.1 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect +) diff --git a/main.go b/main.go index 5995b9b..a5c951d 100644 --- a/main.go +++ b/main.go @@ -1,24 +1,27 @@ package main import ( + "fmt" "github.com/olekukonko/tablewriter" "github.com/tg44/heptapod/pkg" "github.com/tg44/heptapod/pkg/parser" "github.com/tg44/heptapod/pkg/tmutil" + "github.com/tg44/heptapod/pkg/utils" "github.com/urfave/cli/v2" + "io" + "io/ioutil" "log" "os" + "path/filepath" "sort" "strings" ) -func main() { - //res := pkg.GetExcludedPaths([]string{"test-rules/scala.yaml", "test-rules/node.yaml"}, 4, 2048) - //tmutil.AddPathsToTM(res, 2048) - //fmt.Println(len(res)) - - //fmt.Println(tmutil.GetExcludeList()) +var version string = "local-build" +var commit string = "" +var date string = "" +func main() { var rulePath string var logDir string var file string @@ -43,7 +46,7 @@ func main() { &cli.StringFlag{ Name: "logDir", Aliases: []string{"ld"}, - Value: "./.logs", + Value: "~/.heptapod/logs", Usage: "the directory where excluded dirs logged for reliable prune/uninstall", Destination: &logDir, }, @@ -70,6 +73,30 @@ func main() { }, }, Commands: []*cli.Command{ + { + Name: "version", + Aliases: []string{"v"}, + Usage: "version info", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "verbose", + Aliases: []string{"v"}, + Value: false, + Usage: "more detaild version info", + Destination: &verbose, + }, + }, + Action: func(c *cli.Context) error { + if verbose { + fmt.Println(version) + fmt.Println(commit) + fmt.Println(date) + } else { + fmt.Println(version) + } + return nil + }, + }, { Name: "list", Aliases: []string{"ls"}, @@ -108,7 +135,7 @@ func main() { res := pkg.GetExcludedPaths(rulePath, par, buffer, verbose) tmutil.AddPathsToTM(res, logDir, buffer, verbose) if verbose { - log.Printf("total %d paths found", len(res)) + log.Printf("total %d paths found\n", len(res)) } } return nil @@ -166,6 +193,50 @@ func main() { return nil }, }, + { + Name: "initRules", + Aliases: []string{}, + Usage: "copy the example rules to the given rule dir", + Flags: []cli.Flag{}, + Action: func(c *cli.Context) error { + dest, err := utils.FixupPathsToHandleHome(rulePath) + if err != nil { + return err + } + srcDir := "./rules" + entries, err := ioutil.ReadDir(srcDir) + if err != nil { + return err + } + for _, entry := range entries { + sourcePath := filepath.Join(srcDir, entry.Name()) + destPath := filepath.Join(dest, entry.Name()) + + out, err := os.Create(destPath) + if err != nil { + return err + } + defer func() { + _ = out.Close() + }() + + in, err := os.Open(sourcePath) + if err != nil { + return err + } + defer func() { + _ = in.Close() + }() + + _, err = io.Copy(out, in) + if err != nil { + return err + } + } + fmt.Printf("All the rules are copied to %s, please check them with heptapod ls -a, and optionally edit them for better include/exclude rules!\n", rulePath) + return nil + }, + }, }, } diff --git a/pkg/parser/file-trigger_test.go b/pkg/parser/file-trigger_test.go index ef25cd5..3f6dfc5 100644 --- a/pkg/parser/file-trigger_test.go +++ b/pkg/parser/file-trigger_test.go @@ -3,7 +3,7 @@ package parser import "testing" func TestFileTriggerSettingsParse(t *testing.T) { - rule, err := ruleParse("../test-rules/git.yaml") + rule, err := ruleParse("../../test-rules/git.yaml") if err != nil { t.Errorf("Rule parser can't parse testRule!") } diff --git a/pkg/parser/rule_test.go b/pkg/parser/rule_test.go index 6224b8f..ff0f63d 100644 --- a/pkg/parser/rule_test.go +++ b/pkg/parser/rule_test.go @@ -5,7 +5,7 @@ import ( ) func TestRuleParse(t *testing.T) { - res, err := ruleParse("../test-rules/git.yaml") + res, err := ruleParse("../../test-rules/git.yaml") //t.Log(res) if err != nil { t.Errorf("Rule parser can't parse testRule!") diff --git a/pkg/tmutil/tmutil.go b/pkg/tmutil/tmutil.go index 8b18813..26199e3 100644 --- a/pkg/tmutil/tmutil.go +++ b/pkg/tmutil/tmutil.go @@ -13,8 +13,12 @@ import ( "time" ) -func AddPathsToTM(paths []string, logPath string, bufferSize int, verbose bool) { - err := os.MkdirAll(logPath, os.ModePerm) +func AddPathsToTM(paths []string, logDir string, bufferSize int, verbose bool) { + logPath, err := utils.FixupPathsToHandleHome(logDir) + if err != nil { + log.Fatal(err) + } + err = os.MkdirAll(logPath, os.ModePerm) if err != nil { log.Fatal(err) }