1package getter
2
3import (
4	"crypto/md5"
5	"encoding/hex"
6	"fmt"
7	"os"
8	"path/filepath"
9)
10
11// FolderStorage is an implementation of the Storage interface that manages
12// modules on the disk.
13type FolderStorage struct {
14	// StorageDir is the directory where the modules will be stored.
15	StorageDir string
16}
17
18// Dir implements Storage.Dir
19func (s *FolderStorage) Dir(key string) (d string, e bool, err error) {
20	d = s.dir(key)
21	_, err = os.Stat(d)
22	if err == nil {
23		// Directory exists
24		e = true
25		return
26	}
27	if os.IsNotExist(err) {
28		// Directory doesn't exist
29		d = ""
30		e = false
31		err = nil
32		return
33	}
34
35	// An error
36	d = ""
37	e = false
38	return
39}
40
41// Get implements Storage.Get
42func (s *FolderStorage) Get(key string, source string, update bool) error {
43	dir := s.dir(key)
44	if !update {
45		if _, err := os.Stat(dir); err == nil {
46			// If the directory already exists, then we're done since
47			// we're not updating.
48			return nil
49		} else if !os.IsNotExist(err) {
50			// If the error we got wasn't a file-not-exist error, then
51			// something went wrong and we should report it.
52			return fmt.Errorf("Error reading module directory: %s", err)
53		}
54	}
55
56	// Get the source. This always forces an update.
57	return Get(dir, source)
58}
59
60// dir returns the directory name internally that we'll use to map to
61// internally.
62func (s *FolderStorage) dir(key string) string {
63	sum := md5.Sum([]byte(key))
64	return filepath.Join(s.StorageDir, hex.EncodeToString(sum[:]))
65}
66