package main import ( "bufio" "fmt" "os" "path" "sync" ) func oneechan(output chan string) { reader := bufio.NewReader(os.Stdin) for { if text, err := reader.ReadString('\n'); err != nil { fmt.Println("[e] Reading from stdin failed, closing: ", err) break; } else { output <- text[:len(text)-1] } } close(output) } var shadow bool = false func worker(from, to string, wg *sync.WaitGroup) { defer wg.Done() if _, err := os.Stat(from); os.IsNotExist(err) { fmt.Println("[w] input file does not exist: ",from) return } else { fmt.Printf("[i] %v -> %v\n", from, to) } if !shadow { parent_dir, _ := path.Split(to) if _, err := os.Stat(parent_dir); os.IsNotExist(err) { if err := os.MkdirAll(parent_dir, os.ModePerm); err != nil { fmt.Printf("[e] failed to create structure `%s`: %v\n", parent_dir, err) return } } if err := os.Link(from, to); err != nil { fmt.Printf("[e] failed to create hardlink `%s`: %v\n", to, err) } } } func imouto(root string, input chan string) { var wg sync.WaitGroup for from := range input { to := path.Join(root, from) wg.Add(1) go worker(from, to, &wg) } wg.Wait() } func main() { if len(os.Args) < 2 { fmt.Println("usage: glue [--shadow] ") fmt.Println(" -shadow: do not link files or build directory structure") return } i := 1 if os.Args[1] == "--shadow" { shadow = true i+=1 } paths := make(chan string) root := os.Args[i] go oneechan(paths) imouto(root, paths) }