Skip to content

Commit 9315f1e

Browse files
committed
Add track file command
1 parent fb8ca92 commit 9315f1e

File tree

3 files changed

+163
-1
lines changed

3 files changed

+163
-1
lines changed

cmd/shelf/actions.go

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,89 @@ func CreateShelf(cliCtx *cli.Context) error {
4646
return err
4747
}
4848

49-
fmt.Printf("[*] Created a shelf named: %s", shelfName)
49+
// Create a shelf db
50+
_, err = NewDB(shelfPath, shelfName)
51+
if err != nil {
52+
return err
53+
}
54+
55+
fmt.Printf("[*] Created a shelf named: %s\n", shelfName)
56+
57+
return nil
58+
}
59+
60+
// TrackFile tracks the given file.
61+
// The file is moved to the shelf and a symlink is created in its place.
62+
// It stores the filename and symlink path in the shelf's db.
63+
func TrackFile(cliCtx *cli.Context) error {
64+
// Get Home Directory path
65+
home, err := GetHomeDirectory()
66+
if err != nil {
67+
return err
68+
}
69+
70+
shelfName := cliCtx.Args().Get(0)
71+
if shelfName == "" {
72+
return errors.New("Shelf name has to be given")
73+
}
74+
75+
filePath := cliCtx.Args().Get(1)
76+
if filePath == "" {
77+
return errors.New("File path to track can't be blank")
78+
}
79+
80+
// Check if the given shelf exists
81+
_, err = os.Stat(path.Join(home, shelfName))
82+
if err != nil {
83+
if os.IsNotExist(err) {
84+
return fmt.Errorf("Shelf named: %s doesn't exist", shelfName)
85+
}
86+
return err
87+
}
88+
89+
// Check if the file exists and is not a symlink
90+
stat, err := os.Lstat(filePath)
91+
if err != nil {
92+
if os.IsNotExist(err) {
93+
return fmt.Errorf("%s doesn't exist", filePath)
94+
}
95+
return err
96+
}
97+
if stat.Mode()&os.ModeSymlink == os.ModeSymlink {
98+
return fmt.Errorf("%s shouldn't be a symlink", filePath)
99+
}
100+
101+
// Move file to the shelf
102+
err = os.Rename(filePath, path.Join(home, shelfName, path.Base(filePath)))
103+
if err != nil {
104+
return err
105+
}
106+
107+
// Create symlink
108+
err = os.Symlink(path.Join(home, shelfName, path.Base(filePath)), filePath)
109+
if err != nil {
110+
// Since we can't create a symlink, we should put back the file which is moved
111+
err = os.Rename(path.Join(home, shelfName, path.Base(filePath)), filePath)
112+
if err != nil {
113+
return err
114+
}
115+
return err
116+
}
117+
118+
// Put it in the db
119+
db, dbPath, err := GetDB(path.Join(home, shelfName))
120+
if err != nil {
121+
return err
122+
}
123+
db.AddLink(path.Base(filePath), filePath)
124+
f, err := os.Create(dbPath)
125+
if err != nil {
126+
return err
127+
}
128+
err = db.Marshal(f)
129+
if err != nil {
130+
return err
131+
}
50132

51133
return nil
52134
}

cmd/shelf/db.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"io"
6+
"os"
7+
"path"
8+
)
9+
10+
// DB is the db for shelf to store where each symlink is supposed to go.
11+
// This is a JSON File generally stored in
12+
type DB struct {
13+
Name string `json:"name"`
14+
Links map[string]string `json:"links"`
15+
}
16+
17+
// Marshal marshals DB into JSON
18+
func (db *DB) Marshal(w io.Writer) error {
19+
encoder := json.NewEncoder(w)
20+
encoder.SetIndent("", " ")
21+
err := encoder.Encode(&db)
22+
if err != nil {
23+
return err
24+
}
25+
return nil
26+
}
27+
28+
// AddLink adds the file and link paths to the DB
29+
func (db *DB) AddLink(filePath, linkPath string) {
30+
db.Links[filePath] = linkPath
31+
}
32+
33+
// NewDB creates a shelf DB
34+
func NewDB(shelfPath string, shelfName string) (*DB, error) {
35+
db := DB{
36+
Name: shelfName,
37+
Links: make(map[string]string),
38+
}
39+
40+
p := path.Join(shelfPath, "shelf.json")
41+
42+
f, err := os.Create(p)
43+
if err != nil {
44+
return nil, err
45+
}
46+
defer f.Close()
47+
48+
err = db.Marshal(f)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
return &db, nil
54+
}
55+
56+
// GetDB returns the DB in the given shelf
57+
func GetDB(shelfPath string) (*DB, string, error) {
58+
dbPath := path.Join(shelfPath, "shelf.json")
59+
f, err := os.Open(dbPath)
60+
if err != nil {
61+
return nil, "", err
62+
}
63+
defer f.Close()
64+
65+
db := &DB{}
66+
err = json.NewDecoder(f).Decode(db)
67+
if err != nil {
68+
return nil, "", err
69+
}
70+
71+
return db, dbPath, nil
72+
}

cmd/shelf/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ func main() {
1515
Usage: "complete a task on the list",
1616
Action: CreateShelf,
1717
},
18+
{
19+
Name: "track",
20+
Aliases: []string{"t"},
21+
Usage: "track a file",
22+
ArgsUsage: "[shelfname] [filepath]",
23+
Action: TrackFile,
24+
Description: "Tracks given file. The file is moved from the path and a symlink is created in it's place.",
25+
},
1826
},
1927
Name: "shelf",
2028
Description: "A Good Symlinks Manager",

0 commit comments

Comments
 (0)