June 15, 2011

rcat - Concatenate to a remote file

I have recently had the need to do something like "cat file1 >> file2", but where file2 sits on a remote machine. Most users can also think of the most common use case for this, when you have to concatenate your id_rsa.pub (public key) to the authorized_keys list on another machine. I came up with a small hack to do the same which uses rsync behind the scenes, here is how it looks :


#!/bin/bash
#script to remotely concatenate files.
#args -> rcat file1 file2 
#concatenates file1 to remote file file2
local_file=$1
username=`echo $2 | sed 's/:/\t/g' | awk '{print $1}' | sed 's/@/\t/g' | awk '{print $1}'`
remote_host=`echo $2 | sed 's/:/\t/g' | awk '{print $1}' | sed 's/@/\t/g' | awk '{print $2}'`
remote_file=`echo $2 | sed 's/:/\t/g' | awk '{print $2}'`
temp_folder="/tmp/$#/"
file_name=`echo $local_file  | sed 's/\// /g' | awk '{print $NF}'`
if [ -d $local_file ] ;
then
echo "Cannot cat a directory"
echo "Qutting"
exit
fi
rsync $local_file $username@$remote_host:$temp_folder/
ssh $username@$remote_host "cat $temp_folder/$file_name >> $remote_file && rm -rf $temp_folder/"
echo "done"
echo "rcat $local_file $username@$remote_host:$remote_file"

the bad thing about the script right now is that it will ask for authentication twice. But the good thing is that you need not manually sync the files and then concatenate them. The syntax for the remote file is similar to rsync, scp etc. 
rcat [local_file] [username]@[remote_host]:[remote_file]

[EDIT]
There is a utility "ssh-copy-id" to copy the public keys across systems.

June 03, 2011

adding the Power Off option to the statusMenu in gnome-shell

The status menu, which is the dropdown menu to the right most corner on the top panel in gnome 3 contains the Suspend option. This is an alternating option, if you focus on the Suspend option and hit the "Alt" key, you will also see the "Power Off" option.

But I wanted the "Power Off" option to be shown in all cases along with the Suspend option. Here is how I dissected the issue (for the facts, this is the first time I am even looking at gnome 3 code).

1) Located the gnome-shell repository at http://git.gnome.org/browse/gnome-shell/tree/, searched for "Suspend" , and landed at the commit, http://git.gnome.org/browse/gnome-shell/commit/?id=610c2b59872029bceb0279b24dc9637a85f54968.

2) Going through the above commit, figured out that the corresponding UI stuff is in http://git.gnome.org/browse/gnome-shell/tree/js/ui/statusMenu.js

3) Cloned the gnome-shell repository. Edited the file gnome-shell/src/js/ui/statusMenu.js and made the following changes :
--> Made the Suspend option a non-alternating Menu item and display it only if we have suspend support.
--> Added the Power Off option as a new menu item and added a function which would be called when the option is activated.

Voila , I now have the Power Off option as a separate option. Here are the before and after screenshots.


The patch to the latest trunk of the gnome-shell repository which does this is here.

For compiling the gnome-shell code once you have made the changes, follow the usual, "configure", "make" steps and then run "gnome-shell/src/gnome-shell --replace" to use the newly compiled gnome-shell instead of your existing gnome-shell.

This post is more aimed at providing a general flow for fixing issues, not really much in here.

merging commits into a single patch with git-rebase

It is often the scenario that you have cloned a git repository and you have made some changes, now you cannot push to the repository and need to go through a reviewer, so you basically have to submit all your commits to the code as a single patch. Here is how :

We are going to use the repository http://https://github.com/eerpini/git_demo all through the process as the remote repository. It only has a single file, README, and has just one commit with the default branch.

1) Clone the repository :

$ git clone git@github.com:eerpini/git_demo.git

and then change into the directory git_demo.

2) Add a new file :

$ touch new_file
$ echo "Entering something into the new file" >> new_file


3) Since the new file is untracked, "git status" should show something like :

# On branch master
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# new_file
nothing added to commit but untracked files present (use "git add" to track)

4) Add the file and commit :

$ git add new_file
$ git commit -a -m "Adding a new file to the repository"

Note you can now get the change as a patch by doing "git format-patch -1 HEAD". But that is not our goal.

5) Just like above lets commit some more changes(add another file for simplicity).

$ touch new_file_2
$ echo "Entering something into the second new file" >> new_file_2
$ git add new_file_2
$ git commit -a -m "Added the second file to the repository, this should be the second commit"

6) Now we have two commits and "git status" should show you this :

# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
nothing to commit (working directory clean)

7)Now if you want to submit all the changes you have made so far as a single patch, you need to first rebase the two commits into a single one. This is how you do it :

$ git rebase -i origin/master

This will show you the following text in your editor :

pick d5d924c Adding a new file to the repository
pick c0883ac Added the second file to the repository, this should be the second commit

# Rebase 879598c..c0883ac onto 879598c
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.

Edit the above text, basically changing the keywords from pick to something else. If you want only the commit message from one of them, change all the others to fixup or squash. I used squash (edit as follows) :

pick d5d924c Adding a new file to the repository
squash c0883ac Added the second file to the repository, this should be the second commit

Now you can see that both the commits have been combined into a single commit. You can check either using "git log" or "git show HEAD". You can convert these changes into a single patch now using :

$ git format-patch -1 HEAD

In my case, this ended up being :

From 11d19a54021cccdf75e5f16d46eeff89c275be39 Mon Sep 17 00:00:00 2001
From: eerpini
Date: Fri, 3 Jun 2011 01:39:45 -0700
Subject: [PATCH] Adding a new file to the repository

Added the second file to the repository, this should be the second commit
---
new_file | 1 +
new_file_2 | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
create mode 100644 new_file
create mode 100644 new_file_2

diff --git a/new_file b/new_file
new file mode 100644
index 0000000..e3c484b
--- /dev/null
+++ b/new_file
@@ -0,0 +1 @@
+Entering something into the new file
diff --git a/new_file_2 b/new_file_2
new file mode 100644
index 0000000..b4a1e8e
--- /dev/null
+++ b/new_file_2
@@ -0,0 +1 @@
+Entering something into the second new file
--
1.7.5.2