Re wrote backup in go

Previously backup was a cmd plugin writen in bash.
Backup was implemented as a go function, still not in use.
Tests where added since the previous implementation had none.
backup package includes:
 * BackUp function, which performs the actual back up.
 * tarFiles which creates a tar or tar.gz/tgz depending
on the output file name given.
 * runCommand which is a convenience function to simplify testing
since the back up process requires calling external executable
mongoexport.
Ah yes, I remember; that's my fault :-).

In which case, rather than guessing from the name, it would probably
be better to have an explicit "compress" argument to trigger the
behaviour.

For example:

	// tarFiles creates a tar archive at targetPath holding the files listed
	// in fileList. If compress is true, the archive will also be gzip
	// compressed.
	func tarFiles(fileList []string, targetPath string, compress bool) (shaSum string, err error) {
		sha256hash := sha256.New()
		if err := tarAndHashFiles(fileList, targetPath, compress, sha256hash); err != nil {
			return "", err
		}
		return fmt.Sprintf("%x", sha256hash.Sum(nil)), nil
	}
	
	func tarAndHashFiles(fileList []string, targetPath string, compress bool, hashw io.Writer) (err error) {
		checkClose := func(w io.Closer) {
			if closeErr := w.Close(); closeErr != nil && err == nil {
				err = fmt.Errorf("error closing backup file: %v", closeErr)
			}
		}
		f, err := os.Create(targetPath)
		if err != nil {
			return fmt.Errorf("cannot create backup file %q", targetPath)
		}
		defer checkClose(f)
	
		w := io.MultiWriter(f, hashw)
	
		if compress {
			gzw := gzip.NewWriter(w)
			defer checkClose(gzw)
			w = gzw
		}
	
		tarw := tar.NewWriter(w)
		defer checkClose(tarw)
		for _, ent := range fileList {
			if err := writeContents(ent, tarw); err != nil {
				return fmt.Errorf("backup failed: %v", err)
			}
		}
		return nil
	}
	
	// writeContents creates an entry for the given file
	// or directory in the given tar archive.
	func writeContents(fileName string, tarw *tar.Writer) error {
		fInfo, err := os.Stat(fileName)
		if err != nil {
			return err
		}
		h, err := tar.FileInfoHeader(fInfo, "")
		if err != nil {
			return fmt.Errorf("cannot create tar header for %q: %v", fileName, err)
		}
		h.Name = strings.TrimLeft(fileName, string(os.PathSeparator))
		if err := tarw.WriteHeader(h); err != nil {
			return fmt.Errorf("cannot write header for %q: %v", fileName, err)
		}
		if fInfo.IsDir() {
			return nil
		}
		f, err := os.Open(fileName)
		if err != nil {
			return err
		}
		defer f.Close()
		if _, err := io.Copy(tarw, f); err != nil {
			return fmt.Errorf("failed to write %q: %v", fileName, err)
		}
		return nil
	}