Giter Club home page Giter Club logo

bak's Introduction

bak

Note

bak has been abandonware for a little while now. When I got back around to stale PRs and feature requests, I made the most common of unpleasant discoveries among software devs: the first version simply won't do.

As such, bak is being rewritten, with early versions tentatively scheduled for "release" in late February or early March of 2023. I apologize for any inconvenience this period of inactivity, and the following period of "hidden" development, might have caused anyone.

  • ChanceNCounter, maintainer

bak is a command-line utility for creating and restoring backup copies of single files - .bak files - without clutter.

Description and Usage

As residents of the terminal, we all make a lot of on-the-fly, in-place, single-file backups. Config files, dotfiles, "I'm only pretty sure I know what I'm doing" files, before you break them, you do this:

cp my_thing.file my_thing.file.bak

The problem, of course, is remembering to delete that file when you're finished.

bak's goal is simply to obviate this process. Using bak, you'll be able to manage your bakfiles with four simple commands:

bak my_file - Create a bakfile in a configured location (default: XDG_DATA_HOME/bak/bakfiles, or XDG's default location)
bak up my_file - Overwrite current my_file.bak, rather than creating a second .bakfile.
bak down my_file - Deletes my_file and restores it from my_file.bak
bak off my_file - Deletes my_file.bak, confirming by default (bak off -q to suppress)

Don't worry, they're easy to remember after a minute:

bak: bak.
bak up: I've made changes, back them up.
bak down: I've screwed up, undo the damage.
bak off: I'm done working. Go away, bak, and take your .bakfile with you.

All of bak's commands will disambiguate between multiple copies of the same file. In other words, you can bak my_thing.txt as many times as you want, until you're finished working, if you'd prefer to keep multiples instead of using bak up. At the moment, all you've got to go by are timestamps when it asks you to pick a .bakfile, but this will improve.

NOTE: bak down will fall back on sudo cp if necessary. Please don't run sudo bak. This may create parallel config and bakfiles in root's XDG directories.

Additional commands and flags

bak down --keep my_file - Restores from .bakfile, does not delete .bakfile
bak diff my_file Compare a .bakfile using diff (configurable)
bak list/bak list my_file - List all .bakfiles, or just my_file's
bak open my_file View a .bakfile in $PAGER (configurable)
bak open --using exec my_file View a .bakfile using exec (alias --in)

examples:

    bak open --using cat my_file.json
    bak open --in nvim my_file.json

bak where my_file Get the abspath of a .bakfile, in case, for some reason, you want to pipe it somewhere

example (for illustrative purposes; use 'bak diff' instead):

diff `bak where my_file.json` my_file.json

Installation and Requirements

NOTE: This repository's default branch has been changed to unstable for development. For general use, I advise installing the master branch. This will be easier when I get around to proper packaging.

Requires Python3.6 or higher, presumably. Python3.5 has been EOL for 3 months, as of this writing, so if your distro is pegged to it... ouch.

Installation

As the program is currently in an alphaish state, I have decided not to create distro packages yet. I will provide GitHub releases whenever I bump the alpha-alpha version number.

However, if you're comfortable with Python, you can install this repository with the provided setup.py or with pip (just run pip on the local directory.)

If you'd like to hack on bak, I suggest the latter; I'm in the habit of making a project venv, and then doing
pip3 install --editable .

In bak's case, I usually test system-level usage with a simple and naive setup.py install --force

Current state

(updated Jan. 20, 2020)
This is a very pre-alpha version, as in, this is a spaghetti proof-of-concept. Perhaps 5-6 12-15 20 hours have been spent on development so far. As such, it's only "working" in the strictest sense.

At the moment, bak stores its database and your bakfiles in $XDG_DATA_HOME/bak. If $XDG_DATA_HOME is not set, its specified default is used, and your stuff ends up in ~/.local/share/bak.

The config file exists, but could be more intuitive. It's at $XDG_CONFIG_HOME/bak.cfg or ~/.config/bak.cfg and currently accepts values for:

  • The location of your .bakfiles and bakfile DB (I don't recommend changing this)
  • The program to use by default for bak open
  • The program to use by default for bak diff (at the moment, this must support typical diff syntax, as in diff <file1> <file2>)
  • Whether bak list should display relative paths (defaults to False)

If the above sections suggest that a command is implemented, it's working at the most basic level. There are few sanity checks. Expect and please report bugs, as well as feature requests. If you're brave enough to work on a project in the early, mediocre phase, go nuts with the PRs.

Also, there's no very little exception handling (yet.)

Contributing

By and large, I welcome PRs, though I never promise merges.

With an MIT license and GitHub, the licensing situation is a lot more straightforward than in some other cases: you clone this repo, you're getting the code from the author, and the license has the word "irrevocable" in it. Then you're offering a modified version back to the author, with the same license file, still containing the word "irrevocable." What's there to sue about?

So go nuts, if you're so inclined. I have no particular expectations for this project.

bak's People

Contributors

chancencounter avatar serene-arc 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

Watchers

 avatar  avatar

bak's Issues

Implement 'bak list'

bak list should display a list of all .bakfiles, with metadata and so forth. bak list <filename> should display only those .bakfiles corresponding to (obviously.)

Add unit tests; set up GitHub Actions?

The code's not too well documented, but, between my downtime and random passersby, this seems like it oughta be doable in October. test-requires currently has pytest and pytest-cov.

Also, GitHub Actions to run those unit tests would be a bonus. Coverage is the bigger deal.

Trying to bak up file throws error

Doing bak anyfile throws

Traceback (most recent call last):
  File "/home/valence/.local/bin/bak", line 33, in <module>
    sys.exit(load_entry_point('bak==0.2.1a1', 'console_scripts', 'bak')())
  File "/home/valence/.local/bin/bak", line 25, in importlib_load_entry_point
    return next(matches).load()
StopIteration

[Errno 18] Invalid cross-device link when doing `bak down`

So whenever I do bak up, it works, but I also get An error occurred. after the bakfile is made.

And then when I try to do bak down to restore the test file, I get:

Overwrite /home/user/src/bak/TEST? [y/N]: y
Confirm: Restore /home/user/src/bak/TEST to /home/user/src/bak/TEST and erase bakfiles? [y/N]: y
Traceback (most recent call last):
  File "/usr/local/bin/bak", line 33, in <module>
    sys.exit(load_entry_point('bak==0.0.2a1', 'console_scripts', 'bak')())
  File "/usr/lib/python3/dist-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/bak-0.0.2a1-py3.9.egg/bak/__main__.py", line 102, in bak_down
  File "/usr/local/lib/python3.9/dist-packages/bak-0.0.2a1-py3.9.egg/bak/commands/__init__.py", line 274, in bak_down_cmd
  File "/usr/lib/python3.9/pathlib.py", line 1377, in rename
    self._accessor.rename(self, target)
OSError: [Errno 18] Invalid cross-device link: '/root/.local/share/bak/bakfiles/home-user-src-bak-TEST.1613262086-135462.bak' -> '/home/user/src/bak/TEST'

I've been messing around with bak reinstalling and such, but this happens after I've fully uninstalled any past installation and deleted, I believe, all the leftover files. It's possible this might be a permissions problem, but I recently recursively chowned and chmodded my homedir to 751 so that's probably not it. Also, it seemed to work pretty flawlessly on the very first install, no errors with bak up, bak down or anything else.

Disambiguate when multiple bakfiles found

When bak finds multiple .bakfiles matching the filename provided:

  • bak up asks for clarification, or defaults to most recent

  • bak down asks which .bakfile to restore

  • bak off clarifies the number of .bakfiles that will be deleted (confirmation prompt needs to become more granular)

Goes with #13

Implement `bak down`

Implement bak down, the command to delete your modified file and restore it from its .bakfile

Disambiguate between bakfiles during 'bak up/down/off'

When bak finds multiple .bakfiles matching the filename provided:

  • bak up asks for clarification, or defaults to most recent

  • bak down asks which .bakfile to restore

  • bak off clarifies the number of .bakfiles that will be deleted (confirmation prompt needs to become more granular)

Goes with #13

Implement 'bak off'

bak off <filename> is the command to run when you're satisfied with your changes, and want to remove the .bakfile associated with <filename>

Indicate a .bakfile's number when invoking command

If I've just done bak diff foo.cfg, I've just seen the selection menu for foo.cfg. I don't need it to come up again when I run bak down foo.cfg. I should be able to do bak down 2 foo.cfg (slightly less intuitive) or bak down foo.cfg 2 (riskier) to skip the dialog and restore that .bakfile. Since they're always sorted by "last modified"/"last restored" (#37) they're guaranteed to display the same number on the next invocation (assuming you haven't done a bak up in the meantime.)

A few starting issues

I installed this in a virtualenv on my desktop and couldn't get the bak up <file> command to work.
I installed with this process:
git clone git clone https://github.com/bakfile/bak.git
'virtualenv bak/
source bak/bin/activate
python3 bak/setup.py install
When I just typed bak I would get a help menu so I assumed it was installed properly.

The problem occurs when I tried to use bak up test.cfg for the first time I got an error that looks like this:

> bak up test.cfg 
Traceback (most recent call last):
  File "/home/user/bak/bin/bak", line 33, in <module>
    sys.exit(load_entry_point('bak==0.0.1a1', 'console_scripts', 'bak')())
  File "/home/user/bak/lib/python3.6/site-packages/click-7.1.2-py3.6.egg/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/home/user/bak/lib/python3.6/site-packages/click-7.1.2-py3.6.egg/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/home/user/bak/lib/python3.6/site-packages/click-7.1.2-py3.6.egg/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/user/bak/lib/python3.6/site-packages/click-7.1.2-py3.6.egg/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/user/bak/lib/python3.6/site-packages/click-7.1.2-py3.6.egg/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/home/user/bak/lib/python3.6/site-packages/bak-0.0.1a1-py3.6.egg/bak/__main__.py", line 45, in bak_up
  File "/home/user/bak/lib/python3.6/site-packages/bak-0.0.1a1-py3.6.egg/bak/commands/__init__.py", line 227, in bak_up_cmd
  File "/home/user/bak/lib/python3.6/site-packages/bak-0.0.1a1-py3.6.egg/bak/commands/__init__.py", line 95, in _do_select_bakfile

I checked out the offending file and line number and it looks like this:

90    def _do_select_bakfile(bakfiles: List[bakfile.BakFile],
91                          select_prompt=default_select_prompt,
92                           err=True):
93        console = Console(file=stderr if err else stdout)
94        console.print(
95            f"Found {len(bakfiles)} bakfiles for file: {bakfiles[0].orig_abspath}")
96        console.print("Please select from the following: ")
97        console.print("Range %d", len(bakfiles))

On line 95 there is that bakfiles[0] reference, and since the error was a IndexError I figured it was the culprit. I commented those couple of print lines out and reinstalled it. After that I could run the bak up test.cfg command but I didn't really understand the menu that pops up after:

Enter a number to overwrite a .bakfile, or:
(V)iew (L)ist (C)ancel [C]:

This was sort of confusing and I didn't know what to do and after trying all the options I can say that the file seems to not have backed up anything.

I hope this can be a useful issue. I didn't dive into understanding the code much but am willing to help solve it with some direction.
Also, I think there is need for install guide in the README. I found a way to do it but I'm not sure if that is the best way.

Enable bak -h in addition to bak --help

I am used to CLI commands having the -h option for help. I know I can use just bak to see the help message, but often I type the -h by habit. It's very annoying.

Create a proper update mechanism

Relying on hooks probably isn't good enough, either, because who wants to do it twice?

Fortunately, bak can run a version check against config, and store a lightweight file indicating steps per version. Nothing fancy required. Add a breaking doohickey, add a version step.

Implement 'bak print'

bak print <filename> should call $PAGER <bakfile>.
bak print --with <program> <filename> should call <program> <bakfile>
bak print --pipe <filename> should output <bakfile> to stdout, so it can be piped

aliases: -w, -p

Refuse to operate on directories

bak is only designed to work on files. It might someday get an option to work on directories, or perhaps a recursive "bak 'em all" method, because recursive dir copies aren't unheard of. In the meantime, however, bak should catch IsADirectoryError, and output an error instead of crashing.

`bak down` prints `NOT KEEP_BAKFILE: []`

When I run bak down file -k 1, the following message is printed to stdout:

Confirm: Restore /tmp/tuterm/home1/todo.txt from bakfile #1 and  bakfiles ? [y/N]: y
NOT KEEP_BAKFILE: []

I'm assuming this is a python debug message or something. It would be nicer if the message said <N> bakfiles discarded or similar.

Rename 'bak get-bak' if a descriptive name exists

Issue to keep track of suggestions, but if somebody reading this wants to chime in, here's the deal: bak get-bak was chosen because, as far as I can tell, there is no good name for what that does. It's a clunky Beatles reference, for lack of a better idea.

The command outputs the abspath of a .bakfile, which is kind of a niche function. It's for situations where bak open --in exec is too naive to do what you want. To the old version. The backup version. Of a file on which you are currently working.

$bak get-bak ~/bar/baz/foo.txt
/home/you/.local/share/bak/bakfiles/home-you-bar-baz-foo.txt.time-stamp.bak

Throw it in your favorite eval() and enjoy... what a dumb, but occasionally necessary command.

Still, it's the only one with a long name, and the only one with a dash in it, so it might as well get something better.

Suggestions on reddit so far include:

bak get or bak path (/u/posherspantspants)
bak where, bak find, or bak locate (/u/nehtg0ste)

I'm also considering bak loc because it's short. All of these, to me, sound like they imply something more useful than what get-bak does.

Feature request: Specify baks by number from "main" bak list

Hi, I have used this program for a few days and I really like it. One thing did annoy me though. When the file I am backing up is nested deep in a directory tree under my working directory, and I want to restore it using bak down, it is not very convenient to have to specify the file's relative path.

It would be very useful if we could specify the file to restore with bak down using the number, as we can do with bak del. Maybe there is a use case to enable that for other commands as well.

In order to disambiguate a bakfile number from a file that has a number as its name, maybe we can prepend the number with something. For example bak down @1 will restore the bak file numbered 1 and bak down 1 will restore the file ./1. You may have better suggestions than this.

Implement user config

Things are better now that bak respects the XDG directory spec, but it should still be configurable.

Detect rootitude and complain

It won't work everywhere, but if os.geteuid() returns 0, we're definitely root or root-like, and we should tell the user.

WARNING: You are running bak as root! This will create separate config and bakfiles for root, and is probably not what you're trying to do.

If bak needs superuser privileges to copy or overwrite a file, it will invoke `sudo cp` by itself.

Are you sure you want to continue as root? (y,N)

Add commands to alter config

The cfg module is handy for devs, but a little tough on users. bak should
include a set of commands like bak config set and bak config get.

This is awesome!

I just wanted to say, thank you for making this - I love it!
It's so cool having a proper manager for bakfiles, as early in development as it may be. So glad this exists.

(This is not an issue so it can be deleted to prevent clutter. I just wanted to show my appreciation.)

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.