Git Product home page Git Product logo

heptapod's Introduction

heptapod

This is a command line application to manage and fine-tune Time Machine exclude paths.

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.

Install

brew tap tg44/heptapod
brew install heptapod

Usage

To print help;

heptapod -h
heptapod <action> -h

Move (and use) the default ruleset;

mkdir -p ~/.heptapod/rules
cp -R $(brew --prefix heptapod)/rules ~/.heptapod

Lists all the rules (you get 4 tables, enabled, disabled, parseable but unrunable and unparsable).

heptapod rules ls -a

Enable/disable rules (by name), or add/remove ignore folders;

heptapod rules disable node bower
heptapod rules enable bower
heptapod rules ignoreAdd ~/.Trash ~/.yarn/cache ~/Library
heptapod rules ignoreRemove ~/.Trash

List all the currently excluded TM paths;

heptapod tm ls

Dryrun the current rules, in verbose mode, also log speed and debug informations. (Potentially list nonexistent directories and files!)

heptapod -v 1 run -d

To run the current rules, and add the dirs to the TM exclude list. Also writes exclude logs to ~/.heptapod/logs (or the given --logDir dir) for easier revert.

heptapod run

To revert all the previously added paths from the run-exclude-logs. (prune -h could tell you the other useful revert options).

heptapod prune -a

Dictionary

  • path - a file or a folder
  • search path - a path that we want to process
  • ignore path - path that we don't process (further)
  • exclude path - path that we don't want in our TM saves
  • include path - path that we want in our TM saves
  • ignore rule - a rule that parse git/docker ignore file format

Notes from 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.

Notes from TM in general

There are two ways to exclude a dir from backups;

  • exclude by path (tmutil addexclusion -p)
    • needs sudo
    • can be read back with defaults read /Library/Preferences/com.apple.TimeMachine.plist SkipPaths
    • appears in TM preferences / options
  • exclude by flag (tmutil addexclusion)
    • keeps the given flag when moved
    • can not be reliably list them (mdfind com_apple_backup_excludeItem = 'com.apple.backupd' is a close call, but some folders are excluded by mdfind too)

This tool excludes by flag! You can check any folder manually with tmutil isexcluded. If you delete a folder, it will be deleted with its flag. You don't need to clean up ever. Also, you can only exclude nonexcluded files with tmutil, so we only add them if they are exists and if they are not already added.

Rules

Every rule has a searchPaths, ignorePaths.

  • name for categorization
  • enabled for easier enable/disable
  • searchPaths are the root of the rule search like ~
  • ignorePaths are subpaths that we want to ignore to make the run quicker
    • like we want to parse dirs under ~, but not ~/Downloads
  • type is the ruletype
    • file-trigger
    • regexp
    • ignore-file
    • global
    • list
  • settings other type setting see below

Ignore file (not yet implemented)

Parses the .gitignore or .dockerignore files, and excludes its contents.

  • forceIncludePaths are files that we add even if they would be otherwise excluded
    • like .gitignore ignores .env files but we forcefully want to add them back
  • fileName
    • .gitignore or .dockerignore
  • devdocs:
    • the problem with this, that you need to go into the whole subtree to do the parsings

Regexp (not yet implemented)

Ignores all files/folders with the given regexp. This can be slow!

  • regexp

File trigger

Ignores files/dirs based on other files existence, made for easy language dep ignores.

  • fileTrigger like package.json or .git
  • excludePaths like node-modules or .

Global

Globally ignores or excludes path (overrides other rules walk ignores).

  • path the global path we want to evaluate (like ~/.npm)
  • handleWith a string enum
    • ignore - ignores globally
    • exclude - ignores globally and excludes from backups
    • any other value - do nothing

List

Can group multiple rules to a single file.

  • subRules the array of subRules (can be recursive with another list)

Notes;

  • while rules ls works, enable, disable and the path commands not working for the subrules, you need to edit the file manually
  • if the list is disabled, all of it subs are handled as disables
  • the group searchPaths and ignorePaths are currently do nothing
    • probably this will change for easier customisations

Credits

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
  • rule manage commands (list/enable/disable/ignoreAdd/ignoreRemove)
  • global rule type
  • list rule type (for better rule grouping)

todos:

  • reorganise rules
  • fix the rule manage commands for lists
  • 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?

heptapod's People

Contributors

dependabot[bot] avatar lugoues avatar philippmolitor avatar sfleiter avatar tg44 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

heptapod's Issues

Add global directories directly to time machine skip list

Thanks for your great tool. Works like a charm in macOS Monterey!

I want to exclude directories like ~/.yarn-cache/ or ~/.npm/ directly from my time machine backup.
These are 2 example for folders which I want to ignore completely in backups because they make the backup slow.

I looked into rules, but it seems to error prone to do it or too verbose at the moment.
Do you want to extend the rules syntax using the searchPaths for these folders and allow to exclude these folders with a simple hint?

name: "global directories"
enabled: true
searchPaths: ["~/.yarn-cache/", "~/.npm/"]
ignorePaths: []
ruleType: "ignore-directory"

You could disable the rule by default so that the user must activate it first.
What do you think?

Enabling / disabling rules reformats them

The default rules seem to have different formatting from the output generated by the command.

So running:

heptapod rules disable node
heptapod rules enable node

Results in a different file. I started tracking my ~/.heptapod folder in git so I can sync it between machines.

As per #10 though, thanks again, this is really exactly the type of app I wanted for this purpose. Simple, does its job, easy to understand config, amazing!

panic: send on closed channel

This happened when I installed it:

?1 ~ $ brew tap tg44/heptapod
Running `brew update --preinstall`...
==> Auto-updated Homebrew!
Updated Homebrew from 3.4.9 (b4f7dbcc2) to 3.4.10 (bb3d97030).
Updated 4 taps (homebrew/cask-versions, homebrew/core, homebrew/cask and aws/tap).
==> New Formulae
fclones                           libtpms                           vsce
==> Updated Formulae
Updated 153 formulae.
==> Updated Casks
Updated 89 casks.


==> Homebrew was updated to version 3.4.10
The changelog can be found at:
  https://github.com/Homebrew/brew/releases/tag/3.4.10
==> Tapping tg44/heptapod
Cloning into '/usr/local/Homebrew/Library/Taps/tg44/homebrew-heptapod'...
remote: Enumerating objects: 27, done.
remote: Counting objects: 100% (27/27), done.
remote: Compressing objects: 100% (18/18), done.
remote: Total 27 (delta 9), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (27/27), done.
Resolving deltas: 100% (9/9), done.
Tapped 1 formula (12 files, 9.6KB).
~ $ brew install heptapod
==> Downloading https://github.com/tg44/heptapod/releases/download/v0.1.7/heptapod_0.1.7_Darwin_x86_
==> Downloading from https://objects.githubusercontent.com/github-production-release-asset-2e65be/41
######################################################################## 100.0%
==> Installing heptapod from tg44/heptapod
==> Caveats
Start with `heptapod -h`!
==> Summary
๐Ÿบ  /usr/local/Cellar/heptapod/0.1.7: 25 files, 3.7MB, built in 3 seconds
==> Running `brew cleanup heptapod`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
~ $ heptapod -h
NAME:
   heptapod - Fine-tune your TimeMachine excludes!

USAGE:
   heptapod [global options] command [command options] [arguments...]

COMMANDS:
   rules            rule related functions
   run              run the exclude detection, and also exclude the dirs
   timeMachine, tm  timeMachine related functions
   version, v       version info
   help, h          Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --bufferSize value, -b value, --buffer value  number of elements buffered, can cause deadlocks (default: 2048)
   --logDir value, --ld value                    the directory where excluded dirs logged for reliable prune/uninstall (default: "~/.heptapod/logs")
   --parallelism value, -p value, --par value    number of workers where the code is multithreaded (default: 4)
   --rules value, -r value                       the directory containing rule yamls (default: "~/.heptapod/rules")
   --verbose value, -v value                     prints out performance logs (and other logs in general) (0-4) (default: 0)
   --help, -h                                    show help (default: false)
~ $ mkdir -p ~/.heptapod/rules
cp -R $(brew --prefix heptapod)/rules ~/.heptapod
~ $ heptapod rules ls -a
Enabled rules:
                      PATH                      |        NAME        |     TYPE     | SEARCH | IGNORE  
------------------------------------------------+--------------------+--------------+--------+---------
  /Users/Bobik/.heptapod/rules/bower.yaml       | bower              | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/carthage.yaml    | carthage           | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/cocoa-pods.yaml  | CocoaPods          | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/dart.yaml        | dart               | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/go.yaml          | go                 | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/gradle-kt.yaml   | gradle-kotlin      | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/gradle.yaml      | gradle             | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/haskell.yaml     | haskell            | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/maven.yaml       | maven              | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/node.yaml        | node               | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/osx.yaml         | node-multi         | list         |        |         
  /Users/Bobik/.heptapod/rules/osx.yaml         | node-multi/library | global       |        |         
  /Users/Bobik/.heptapod/rules/php.yaml         | php                | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/python-pip.yaml  | python-pip         | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/python-pypi.yaml | python-pypi        | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/python-tox.yaml  | python-tox         | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/python-venv.yaml | python-venv        | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/ruby.yaml        | ruby               | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/rust.yaml        | rust               | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/scala-sbt.yaml   | scala-sbt          | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/swift.yaml       | swift              | file-trigger | ~      |         
  /Users/Bobik/.heptapod/rules/vagrant.yaml     | vagrant            | file-trigger | ~      |         
Disabled rules:
                  PATH                  |         NAME         |  TYPE  | SEARCH | IGNORE  
----------------------------------------+----------------------+--------+--------+---------
  /Users/Bobik/.heptapod/rules/osx.yaml | node-multi/downloads | global |        |         
  /Users/Bobik/.heptapod/rules/osx.yaml | node-multi/trash     | global |        |         
Errors:
  NONPARSEABLE FILES  
----------------------
Type parse errors:
  PATH | NAME | TYPE  
-------+------+-------
~ $ heptapod -v 1 run -d
panic: send on closed channel

goroutine 19 [running]:
github.com/tg44/heptapod/pkg/walker.worker(0x0, 0x0, 0x0, 0x0, 0x0)
	/home/runner/work/heptapod/heptapod/pkg/walker/walker.go:69 +0x105
created by github.com/tg44/heptapod/pkg/walker.Run
	/home/runner/work/heptapod/heptapod/pkg/walker/walker.go:43 +0x29b

macOS Monterey?

Hi! I'm really interested in this script. Is this functional on Monterey? Homebrew installs in opt/homebrew from MacOS 12 and I wonder if it all works smoothly on it.

BTW, How do we add or modify rules? For example for Python projects I don't use requirements.txt but Pipfile. Can see that file to trigger the exclusion of .venv folders too?

Thanks!

Warning from Homebrew

When installing on my Mac I got this:

Warning: Calling bottle :unneeded is deprecated! There is no replacement.
Please report this issue to the tg44/heptapod tap (not Homebrew/brew or Homebrew/core):
  /opt/homebrew/Library/Taps/tg44/homebrew-heptapod/heptapod.rb:10

So I wanted to report it to you in case you need to fix it.

Edit: I think goreleaser fixed this in version v0.183.0 - I think Homebrew deprecated the use of bottle :unneeded after you published your latest version of heptapod, so I guess it will be automatically fixed in your next release if you update goreleaser

Yaml rule parse error

Hi, I don't want to be a pain in the ass, but just want your app to work, so I'm trying all combinations of folder creation, etc, and sometimes I get the following error. It happened in Monterey and now it's happening in Catalina.

I'm not sure if this tells you anything.

Screenshot 2022-01-01 at 15 37 24

In order to get rid of the error I have to delete the .heptapod folder and recreate it, and copy the rules again.

Thanks

This looks like exactly what I was thinking to write (although I figured I'd test out rust). Thanks for sharing it.

I really appreciate the simplicity and the fact that I can dry run to see what's going to happen. Hopefully the GitHub star count rises and folks start to see this as a viable alternative to asimov and the seemingly abandoned tmignore.

Dependencies are heavily out of date

Some dependencies are very much outdated.

# go list -u -m all
github.com/tg44/heptapod
github.com/BurntSushi/toml v0.3.1 [v1.3.2]
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d [v2.0.2]
github.com/mattn/go-runewidth v0.0.9 [v0.0.15]
github.com/olekukonko/tablewriter v0.0.5
github.com/pmezard/go-difflib v1.0.0
github.com/russross/blackfriday/v2 v2.0.1 [v2.1.0]
github.com/shurcooL/sanitized_anchor_name v1.0.0
github.com/urfave/cli/v2 v2.3.0 [v2.25.7]
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 [v1.0.0-20201130134442-10cb98267c6c]
gopkg.in/yaml.v2 v2.4.0

.venv folders not being ignored

Hi!

I open a new issue to keep things a bit more organised.

The app is working really a lot more reliably, but .venv folders are not being ignored after running.

Others, non dot folders are working great and I don't have now node_modules folders in my Time Machine backups, but .venv are still there.

They don't show up either when I run heptapod tm ls, so perhaps there's an issue with the dot starting the name of the folder?

I hope I'm clear!

Note: The .venv folders show up in the dryrun and the log file, but are not added to the Time Machine Ignore.

Feature Request: Add hostname to log file or name

As I'm tracking ~/.heptapod in git and syncing it between machines, I realise that I won't know which log files were generated on which machines. Any chance you'd be open to adding the hostname either in the filename or as part of the log file?

For example, maybe ~/.heptapod/logs/${host}_${time}.log could work?

Using hostname -s seems to print out just the name without the domain part, which would be perfect in my opinion.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.