Tagref helps you maintain cross-references in your code.

Overview

Tagref

Build status

Tagref helps you maintain cross-references in your code. You can use it to help keep things in sync, document assumptions, manage invariants, etc. Airbnb uses it for their front-end monorepo. You should use it too!

What is it?

When writing code, it's common to refer to other parts of the codebase in comments. The traditional way to do that is to provide a file path and a line number. For example:

# Keep this in sync with controllers/profile.py:304.

Unfortunately, as we all know, this is brittle:

  1. As the code evolves, the line numbers may shift.
  2. The file might be renamed or deleted.

One strategy is to reference a specific commit. At least then you know the reader will be able to find the line that you're referencing:

# Keep this in sync with controllers/profile.py@55217c6:304.

But that approach isn't ideal, since the current version of the code may have diverged from the referenced commit in non-trivial ways.

Tagref solves this problem in a better way. It allows you to annotate your code with tags (in comments), which can be referenced from other parts of the codebase. For example, you might have a tag like this:

# [tag:cities_nonempty] This function always returns a non-empty list.
def get_cities():
  return ['San Francisco', 'Tokyo']

Elsewhere, suppose you're writing some code which depends on that postcondition. You can make that clear by referencing the tag:

cities = get_cities()

first_city = cities[0] # This is safe due to [ref:cities_nonempty].

Tagref ensures such references remain valid. If someone tries to delete or rename the tag, Tagref will complain. More precisely, it checks the following:

  1. References actually point to tags. A tag cannot be deleted or renamed without updating the references that point to it.
  2. Tags are unique. There is never any ambiguity about which tag is being referenced.

Note that, in the example above, Tagref won't ensure that the get_cities function actually returns a non-empty list. It isn't magic! It only checks the two conditions above.

Tagref works with any programming language, and it respects your .gitignore file as well as other common filter files. It's recommended to set up Tagref as an automated continuous integration check. Tagref is blazing fast (as they say) and almost certainly won't be the bottleneck in your CI.

Usage

The easiest way to use Tagref is to run the tagref command with no arguments. It will recursively scan the working directory and check the two conditions described above. Here are the supported command-line options:

USAGE:
    tagref [SUBCOMMAND]

OPTIONS:
    -h, --help
            Prints help information

    -p, --path 
   
    ...
            Adds the path of a directory to scan [default: .]

    -r, --ref-prefix 
    
     
            Sets the prefix used for locating references [default: ref]

    -t, --tag-prefix 
     
      
            Sets the prefix used for locating tags [default: tag]

    -v, --version
            Prints version information

SUBCOMMANDS:
    check
            Checks all the tags and references (default)

    help
            Prints this message or the help of the given subcommand(s)

    list-refs
            Lists all the references

    list-tags
            Lists all the tags

    list-unused
            Lists the unreferenced tags

     
    
   

Installation instructions

Installation on macOS or Linux (x86-64)

If you're running macOS or Linux on an x86-64 CPU, you can install Tagref with this command:

curl https://raw.githubusercontent.com/stepchowfun/tagref/main/install.sh -LSfs | sh

The same command can be used again to update to the latest version.

The installation script supports the following optional environment variables:

  • VERSION=x.y.z (defaults to the latest version)
  • PREFIX=/path/to/install (defaults to /usr/local/bin)

For example, the following will install Tagref into the working directory:

curl https://raw.githubusercontent.com/stepchowfun/tagref/main/install.sh -LSfs | PREFIX=. sh

If you prefer not to use this installation method, you can download the binary from the releases page, make it executable (e.g., with chmod), and place it in some directory in your PATH (e.g., /usr/local/bin).

Installation on Windows (x86-64)

If you're running Windows on an x86-64 CPU, download the latest binary from the releases page and rename it to tagref (or tagref.exe if you have file extensions visible). Create a directory called Tagref in your %PROGRAMFILES% directory (e.g., C:\Program Files\Tagref), and place the renamed binary in there. Then, in the "Advanced" tab of the "System Properties" section of Control Panel, click on "Environment Variables..." and add the full path to the new Tagref directory to the PATH variable under "System variables". Note that the Program Files directory might have a different name if Windows is configured for a language other than English.

To update to an existing installation, simply replace the existing binary.

Installation with Cargo

If you have Cargo, you can install Tagref as follows:

cargo install tagref

You can run that command with --force to update an existing installation.

Acknowledgements

The idea for Tagref was inspired by the GHC notes convention. This article has more insights into how the GHC developers manage their codebase.

You might also like...
For when you really, really just want to know that your config changed

really-notify This crate is for when you really, really just want to know that your config changed. K8s configmap symlink shenanigans? No problem. Mul

Clean up the lines of files in your code repository

lineman Clean up the lines of files in your code repository NOTE: While lineman does have tests in place to ensure it operates in a specific way, I st

Rate limit guard - Lazy rate limit semaphore implementation to control your asynchronous code frequency execution

Lazy rate limit semaphore (a.k.a fixed window algorithm without queueing) implementation to control your asynchronous code frequency execution

A cross-platform serial port library in Rust.

Introduction serialport-rs is a general-purpose cross-platform serial port library for Rust. It provides a blocking I/O interface and port enumeration

Cross-platform Window library in Rust for Tauri. [WIP]

Cross-platform application window creation library in Rust that supports all major platforms like Windows, macOS, Linux, iOS and Android. Built for you, maintained for Tauri.

A cross platform tool which instantly notifies about COVID vaccine availability.
A cross platform tool which instantly notifies about COVID vaccine availability.

💉 CoWIN Notifier 😷 A cross-platform tool written in rust, which instantly notifies users about COVID-19 vaccine availability at their regions. Curre

A rewrite of Phonelink for Windows Forms written in Rust, with cross-platform support.

phonelink-rs A rewrite of Phonelink for Windows Forms written in Rust, with cross-platform support. Usage Clone the repository and build, or download

A cross-platform launcher for Fish Fight 🐠
A cross-platform launcher for Fish Fight 🐠

Fish Fight Launcher A cross-platform launcher for Fish Fight. Features Install and launch (via GUI/CLI) Auto updates Mod management Download See avail

A cross-platform serial port library in Rust. Provides a blocking I/O interface and port enumeration including USB device information.

Note: This is a fork of the original serialport-rs project on GitLab. Please note there have been some changes to both the supported targets and which

Comments
  • Tagref ignores tags in dot files

    Tagref ignores tags in dot files

    Description

    I have a dot file that is not gitignored and checked into the repo. Tagref seems to ignore any tags in the dot file and acts like they don't exist. This is happening on version 1.3.0 & 1.3.1.

    ❯ tagref --version 
    Tagref 1.3.1
    

    Instructions to reproduce the bug Add a dot file to the repo containing a tag:

    // .happo.js
    [tag: foo]
    

    add a reference to the tag in a file with a name that doesn't begin with a dot

    // cypress.json
    [ref: foo]
    

    this will result in the following error during lint:

    ❯ tagref                    
    No tag found for [ref:foo] @ ./cypress.json:1.
    

    System information:

    • OS: macOS Catalina 10.15.7
    • Tagref version: 1.3.0

    Additional context Hi Stephan!

    bug 
    opened by sharmilajesupaul 3
Releases(v1.5.0)
Owner
Stephan Boyer
Engineering @Google, previously @Airbnb, @Dropbox, @MIT. Trying to turn abstract nonsense into useful technology.
Stephan Boyer
Helps positioning your tauri windows.

Tauri plugin positioner A plugin for tauri that helps positioning you windows at well known locations. Install Rust [dependencies] tauri-plugin-positi

Jonas Kruckenberg 42 Jan 5, 2023
Bongo Copy Cat wants to be involved in everything you do but instead just imitates you hitting your keyboard all day. After all it's just a cat.

Bongo Copy Cat Introduction Bongo Copy Cat wants to be involved in everything you do but instead just imitates you hitting your keyboard all day. Afte

Abhijeet Singh 4 Jan 23, 2023
Twidge is a fresh approach to productivity. It integrates with your workflow and allows you to be your most productive self.

Twidge A productivity app which is an extension to your mind Twidge is a cross platform productivity app, powered by rust, tauri, prisma-client-rust T

Twidge 187 Jun 28, 2023
Fusion is a cross-platform App Dev ToolKit build on Rust . Fusion lets you create Beautiful and Fast apps for mobile and desktop platform.

Fusion is a cross-platform App Dev ToolKit build on Rust . Fusion lets you create Beautiful and Fast apps for mobile and desktop platform.

Fusion 1 Oct 19, 2021
Searchbuddy is a browser extension that lets you chat with people that are searching for what you're searching for.

searchbuddy Make friends while searching! Searchbuddy is a browser extension that lets you chat with people that are searching for what you're searchi

Joseph Gerber 14 May 23, 2022
Flexcord! A custom Discord client to allow you to do what you want!

Disclaimer Flexcord is NO WHERE near done. Flexcord What is it? Flexcord is a Discord client that flexes for your needs, it allows you to do exactly w

null 2 Dec 5, 2022
Cross-platform bookmarks manager for your shell

shellmark: bookmark manager for shell THIS IS AN EARLY ALPHA. It works for me, but requires better UX and more polish. shellmark is a cross-platform b

Artem Pyanykh 25 Nov 10, 2022
The lambda-chaos-extension allows you to inject faults into Lambda functions without modifying the function code.

Chaos Extension - Seamless, Universal & Lightning-Fast The lambda-chaos-extension allows you to inject faults into Lambda functions without modifying

AWS CLI Tools 5 Aug 2, 2023
miette is a diagnostic library for Rust. It includes a series of traits/protocols that allow you to hook into its error reporting facilities, and even write your own error reports!

miette is a diagnostic library for Rust. It includes a series of traits/protocols that allow you to hook into its error reporting facilities, and even write your own error reports!

Kat Marchán 1.2k Jan 1, 2023
Redirects your plumbing for you.

Valve _Redirects your plumbing for you. _ valve creates multi-threaded Plumber APIs powered by Rust's tokio and axum web frameworks. Motivation Plumbe

Josiah Parry 37 Jun 13, 2023