DEV Community

sasurau4
sasurau4

Posted on

Wrote a cli tool in Rust

Intro

I wrote a simple cli tool named github-cli-utils in Rust. This tool suppports daily OSS activity in GitHub.

I'll introduce why and how write it!

Usage

Install from crate.io

cargo install github-cli-utils

After you installed github-cli-utils, you run it and show following.

λ github-cli-utils help
github-cli-utils 0.1
Daiki Ihara <sasurau4@gmail.com>
Support developing OSS via cli

USAGE:
    github-cli-utils [FLAGS] <SUBCOMMAND>

FLAGS:
    -d, --debug      Turn debugging information on
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    add-upstream    add upstream to your git repository
    help            Prints this message or the help of the given subcommand(s)

This tool provide add-upstream command. It add upstream repository to your forked repository!

Motivation

My motivation of writing github-cli-utils is 2 following points.

  1. Add upstream is a bit troublesome
  2. Curiosity to Rust
  3. Needs to platform and shell agonistic command

Add upstream is a bit troublesome

When you find a bug or typo at readme about the OSS, you forked the repository, clone it and add upstream.

Adding upstream is a bit troublesome because it needs to copy parent repository's url in browser.

Going back and forth between terminal and browser is annoying, isn' it?

Curiosity to Rust

I've been curious to Rust for about 2 years...

Time has passed and congrats five years from Rust's birth.

I began to write the simple cli tool to solve my daily little trouble.

Needs to platform and shell agonistic command

I use macOS in my work and also use Ubuntu in my private coding. The enviroment is a bit different.

If I just want to achieve my usecase, I would done it by writing shell script like following.

git-remote-add-upstream() {
  if ! type jq > /dev/null 2>&1; then
    echo "'jq' is not installed." >&2
    exit 1
  fi
  if [ $# -ne 1 ]; then
    echo "Need repo name. e.g : 'user/repo'"
    exit 1
  fi
  local upstream=$(curl -L "https://api.github.com/repos/$1" | jq -r '.parent.full_name')
  if [ "$upstream" = "null" ]; then
    echo "upstream not found." >&2
    exit 1
  fi
  git remote add upstream "git@github.com:${upstream}.git"
}
alias grau='git-remote-add-upstream'

This script is quoted from https://tech-blog.sgr-ksmt.org/2016/03/04/git_remote_add_upstream/

It's very fine, but need to be jq command installed. To be worse, I'm using fish shell.
So I wrote a command that add upstream automatically without thinking about platform and shell.

Hard point of implementation

The codes is https://github.com/sasurau4/github-cli-utils.

Argument parsing

I used clap to parse argument. clap is useful library for that purpose.

I implemented add-upstream by subcommand. I wanted to use debug argument after command like github-cli-utils add-upstream --debug.
In default, clap only allows flags place before subcommand like github-cli-utils [FLAGS] <SUBCOMMAND>. I had to use global(true) in argument setting to allow flags placed after subcommand.

Https access

At first, I use hyper as http client. It's very useful but a bit complicated when accessing some resource via https.1

I use reqwest instead of hyper. It's very easy to use.

Conclusion

Rust is a good language to implement cli tool thanks to language itself and the ecosystem.
I hope this article help you implement cli tools.

Also, I'm welcome PRs and issues to github-cli-utils!


  1. https://github.com/hyperium/hyper/issues/1025 

Top comments (0)