// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"archive/tar"
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var output = flag.String("output", "", "Path to the generated tarball")
var manifest = flag.String("manifest", "", "Path to the file containing a description of the tarball's contents")

func archiveFile(tw *tar.Writer, src, dest string) error {
	file, err := os.Open(src)
	if err != nil {
		return err
	}
	defer file.Close()
	info, err := file.Stat()
	if err != nil {
		return err
	}

	hdr, err := tar.FileInfoHeader(info, info.Name())
	if err != nil {
		return err
	}
	hdr.Name = dest
	hdr.Uid = 0
	hdr.Gid = 0
	if err := tw.WriteHeader(hdr); err != nil {
		return err
	}
	_, err = io.Copy(tw, file)
	return err
}

func archiveDirectory(tw *tar.Writer, src, dest string) error {
	return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		fileDest := filepath.Join(dest, path[len(src)+1:])
		return archiveFile(tw, path, fileDest)
	})
}

func createTar(archive string, mappings map[string]string) error {
	file, err := os.Create(archive)
	if err != nil {
		return err
	}
	defer file.Close()

	w := NewWriter(file)
	defer w.Close()
	tw := tar.NewWriter(w)
	defer tw.Close()

	for dest, src := range mappings {
		info, err := os.Stat(src)
		if err != nil {
			return err
		}
		if info.IsDir() {
			err = archiveDirectory(tw, src, dest)
		} else {
			err = archiveFile(tw, src, dest)
		}
		if err != nil {
			return err
		}
	}

	return nil
}

func readManifest(manifest string) (map[string]string, error) {
	file, err := os.Open(manifest)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	result := make(map[string]string)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		parts := strings.SplitN(scanner.Text(), "=", 2)
		result[parts[0]] = parts[1]
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return result, nil
}

func generateArchive(manifest string, output string) error {
	if _, err := os.Stat(output); err == nil {
		// The file exists, need to remove it first.
		if err := os.Remove(output); err != nil {
			return err
		}
	}
	mappings, err := readManifest(manifest)
	if err != nil {
		return err
	}
	return createTar(output, mappings)
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, `Usage: tar_maker --manifest path/to/manifest

This tool creates a tarball whose contents are described in a file manifest.
Each line in the manifest should be of the form:
    <path in tarball>=<path to source file or dir>

The tarball is compressed using gzip.
`)
		flag.PrintDefaults()
	}
	flag.Parse()

	if *output == "" {
		flag.Usage()
		log.Fatalf("Error: missing -output flag.")
	}
	if *manifest == "" {
		flag.Usage()
		log.Fatalf("Error: missing -manifest flag.")
	}

	if err := generateArchive(*manifest, *output); err != nil {
		log.Fatalf("Error: unable to create archive %s: %v", *output, err)
	}
}
