forked from knieriem/hgo
-
Notifications
You must be signed in to change notification settings - Fork 4
/
hg.go
116 lines (101 loc) · 2.68 KB
/
hg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright 2013 The hgo 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 hgo provides read access to Mercurial repositories.
package hgo
import (
"errors"
"os"
"path/filepath"
"strings"
"github.com/beyang/hgo/store"
)
// http://mercurial.selenic.com/wiki/FileFormats
// Find the root of a project, given the name of a file or directory
// anywhere within the project's directory tree.
func FindProjectRoot(orig string) (root string, err error) {
isRel := !filepath.IsAbs(orig)
origAbs, err := filepath.Abs(orig)
if err != nil {
return
}
path := origAbs
// if path is not a directory, skip the last part; (ignore an error,
// because it is not important whether `path' exists at this place)
if fi, err := os.Stat(path); err == nil && !fi.IsDir() {
path = filepath.Dir(path)
}
for {
if fi, err1 := os.Stat(filepath.Join(path, ".hg")); err1 == nil && fi.IsDir() {
break
}
old := path
path = filepath.Clean(filepath.Join(path, ".."))
if path == old {
err = errors.New("no repository found")
return
}
}
// found
root = path
if isRel {
// if the original path was a relative one, try to make
// `root' relative to the current working directory again
if wd, err1 := os.Getwd(); err1 == nil {
if r, err1 := filepath.Rel(wd, path); err1 == nil {
root = r
}
}
}
return
}
type Repository struct {
root string
requires map[string]bool
}
// Open a repository located at the given project root directory,
// i.e. a directory that contains a subdirectory named ‘.hg’.
func OpenRepository(root string) (r *Repository, err error) {
var t Repository
t.root = root
f, err := t.open(".hg/requires")
if err != nil {
return
}
t.requires, err = parseRequires(f)
f.Close()
if err != nil {
return
}
r = &t
return
}
// For a given absolute or relative file name, compute a name relative
// to the repository's root.
func (r *Repository) RelFileName(name string) (rel string, err error) {
absName, err := filepath.Abs(name)
if err != nil {
return
}
absRoot, err := filepath.Abs(r.root)
if err != nil {
return
}
rel, err = filepath.Rel(absRoot, absName)
if err != nil {
return
}
rel = filepath.ToSlash(filepath.Clean(rel))
if rel == ".." || strings.HasPrefix(rel, "../") {
rel = filepath.ToSlash(name)
}
return
}
// NewStore returns a new Store instance that provides
// access to the repository's changelog, manifests, and filelogs.
func (r *Repository) NewStore() *store.Store {
return store.New(r.root, r.requires)
}
func (r *Repository) open(name string) (*os.File, error) {
return os.Open(filepath.Join(r.root, filepath.FromSlash(name)))
}