You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
sources-peterbabic.dev/how-commit-history-tells-wh...
Peter Babič 60dcc7e874
insert posts sources
3 years ago
..
.gitignore insert posts sources 3 years ago
README.md insert posts sources 3 years ago
added.ts insert posts sources 3 years ago
example-diff.js insert posts sources 3 years ago
package-lock.json insert posts sources 3 years ago
package.json insert posts sources 3 years ago
revvalk.ts insert posts sources 3 years ago
test.js insert posts sources 3 years ago

README.md

Introduction

This repository serves as a proof-of-concept and starting point for using nodegit to figure out when a file was created and when it was last updated, not based on timestamps (atime, ctime, mtime) but based solely on commit history.

Motivation

The way how timestamps are set is distribution dependent. Or in other words, they depend on atime option set in /etc/fstab/. You can read about different options in an Arch wiki.

The way how timestamps are read also depends on access to the filesystem, which may or may not be avaiable. Overall, for the purpose of tracking when a markdown file was created and updated, this is not a universal, nor a portable solution.

Alternatives

A common solution to this problem is to store this timestamps in a database of some kind. But setting up a database just for the purpose of storing a filename and it's timestamps might not be desirable. This also adds a complexity in a form of synchronizing the filenames in the filesystem and a database.

Of course, when the database with the timestamps is already there, one could just store the entire markdown content in itm instead of just the filename, but then again, you cold not write the markdown file easily with your editor.

Solution

In a git based workflow, the required timestamps are already stored in a repository. According to a StackOverflow question this can be done like this:

# get a commit where a file foo.js was created
git log --diff-filter=A -- foo.js

Using a git-diff documentation we can elaborate further:

# get a commit where a file foo.js was modified
git log --diff-filter=M -- foo.js

This proves that the task can be done. However, ideally we need to do it programatically, without the need for running bash, which could also be OS dependent, but natively in javascript. A layer of abstraction that servers as a wrapper of git commands would suffice, because it would presumably be less OS dependent.

Solution

As with the most things in a javascript world, not one, but multiple such abstraction layers / wrappers already exists. I would not list them all here. Instead, without any research, somehow nodegit appealed to me as a best tool for the job.

Running npm run dev shows the dates when file added.ts was created and modified based on the commit history.

Caveat

One problem that I have found with this approach is renaming the file. We use fileHistoryWalk for walking the commit history. It returns an array of objects of type <HistoryEntry>, which looks like it is not documented in an API as of time of writing. Each object contains a commit, a date and a status entry. The first two are easy to work with but, since it is not documented, at first I could not find out what that status means. Experimentally I have found it correlates to the diff delta enum.

We can see, that value 4 stands for RENAMED, but since, we walk the history of just one file, and renaming actually creates two filenames in a commit history, this results in lost data. However, when not renaming files, it works like a charm.

Notes

  • typescript is used here instead of javascript
  • date-fns is used for formatting the timestamps

Further reading

License

MIT