Saturday, July 30, 2016

Nerd-Code Snippets 1: Mercurial alias and bash crash-course

Disclaimer

Most of you aren’t going to have a clue what I’m talking about. I sincerely apologize ahead of time. I’ll attempt a layman’s explanation, but I make no promises. I’ll try to link to unfamiliar terms.

Backstory

Even before my new job - oh yea, by the way, I’m a web developer now, fancy that - I was practicing with DVCS as a hobby. A Distributed Version Control System is just a way of tracking the history of source code files throughout the life of a project. There are two major DVCS’s out there, Git and Mercurial. It seems Git is more widely used and more widely accepted for projects with multiple developers (and I’m learning it for work), but I like to use Mercurial for my personal projects because that’s what I taught myself.

One of the things you do in a DVCS is push your local repository of code-history to a remote repository. Its a way of backing up to a cloud service, but you can also track the history on that remote site. I use Bitbucket.org for my personal stuff (turns out we use it for work, as well, and Bitbucket can use Git or Mercurial without issue).
There are definitely GUIs out there for using Git or Mercurial, but I like to do stuff from the command line a lot of the time.

Problem

When I’m setting up a new Bitbucket repository, or changing the name of current one, I have to change a file in my local repository that points to the remote repository. If it doesn’t already exist to edit, I have to change that file to represent something like this:
[paths]
default = ssh://hg@bitbucket.org/username/repo_name
ssh = ssh://hg@bitbucket.org/username/repo_name
https = https://bitbucket.org/username/repo_name
These allow me to push my changes to that Bitbucket repository with a simple command like push ssh or push https or even just push. But I’m lazy and I hate opening that file to edit in vim, so for fun - wait, did I call myself lazy? - I wrote an hg (mercurial) alias that does it in three words or less …

Solution

hg setpaths repo_name or simply hg setpaths will put the previous lines of code into .hg/hgrc. Here is what that portion of my global .hgrc looks like:
[paths]
default = ssh://hg@bitbucket.org/username
ssh = ssh://hg@bitbucket.org/username
https = https://bitbucket.org/username

[alias]
setpaths = !if [ $1 ]; then it=$1; else it=${PWD##*/}; fi; echo "[paths]\ndefault = `hg config paths.default`/$it\nssh = `hg config paths.ssh`/$it\nhttps = `hg config paths.https`/$it" > .hg/hgrc

Bash Crash & Breakdown

That was a mouthful, eh? I’ll break it down into as many small pieces as I possibly can. By the way, if you were here for the layman’s dialogue, this is where that ends. Abruptly. In fact, it started to end at the beginning of the last header… I’m just going to dive straight into the alias itself, now:
  • ! - this allows me to execute what follows in bash
  • if [ $1 ]; then it=$1; else it=${PWD##*/}; fi; - this is a one-liner if statement that takes the 1st argument, repo_name, and assigns it to a variable I can use. If not supplied, it uses the name of the directory in which the command is called
    • ${PWD##*/} - I got this from a stack-overflow post. Thanks Google. Its an ugly-but-effective bash parameter expansion that strips everything but the base name of the working directory.
  • echo "[paths]\ndefault = `hg config paths.default`/$it\nssh = `hg config paths.ssh`/$it\nhttps = `hg config paths.https`/$it" - four dynamic lines in one string
    • \n - is the newline character that splits it up into four separate lines
    • hg config paths.default - snags the paths.default value in from the global file (right above our alias) and pops it into our string so I don’t have to type it all the way out.
      • similar idea for paths.ssh and paths.https. These are the three I typically use, but I could theoretically approach this in a different way (maybe using regex’s and sed)
    • $it - just using that variable I set earlier in that if statement…
  • > .hg/hgrc - redirects the echo’d string into the local repository’s settings file (overwriting it). Its okay to ovewrite it because frankly, these lines are all I ever store in there.

Conclusion

Waste of time? Maybe. Fun and entertaining (and later, quite useful)? Definitely.
This is all a part of a larger picture, by the way. A larger picture of having a repository of my configs or settings for tools like vim, mercurial, git, bash, tmux, etc. There will be more of these posts.
Nerd-life. No shame.

Table of Contents


Written with StackEdit.

No comments:

Post a Comment

Please keep your comments respectful and in the spirit of constructive criticism.