Merge branch 'master' into v0.12

* master:
  Update docs and translations
  Model.internalScanFolder: Don't ignore special .stfolder and .stignore files.
  Model.internalScanFolderSubs: Scan only requested subs.
  A couple of protocol tests
  Humanize serialization of version vectors (again)
  FetchLatestReleases: fix the error log message
  Add postinst script to restart after upgrade
  Templatize Debian files
  Don't require restart for usage reporting changes (fixes #2704)
  RLimit comment typo
This commit is contained in:
Jakob Borg
2016-01-24 08:09:28 +01:00
33 changed files with 204 additions and 70 deletions
File diff suppressed because one or more lines are too long
+17 -9
View File
@@ -67,7 +67,7 @@ type Model struct {
finder *db.BlockFinder
progressEmitter *ProgressEmitter
id protocol.DeviceID
shortID uint64
shortID protocol.ShortID
cacheIgnoredFiles bool
protectedFiles []string
@@ -1323,15 +1323,14 @@ func (m *Model) internalScanFolderSubs(folder string, subs []string) error {
var unifySubs []string
nextSub:
for _, sub := range subs {
for sub != "" {
parent := filepath.Dir(sub)
if parent == "." || parent == string(filepath.Separator) {
parent = ""
}
if _, ok = fs.Get(protocol.LocalDeviceID, parent); ok {
for sub != "" && sub != ".stfolder" && sub != ".stignore" {
if _, ok = fs.Get(protocol.LocalDeviceID, sub); ok {
break
}
sub = parent
sub = filepath.Dir(sub)
if sub == "." || sub == string(filepath.Separator) {
sub = ""
}
}
for _, us := range unifySubs {
if strings.HasPrefix(sub, us) {
@@ -1959,7 +1958,16 @@ func (m *Model) CommitConfiguration(from, to config.Configuration) bool {
}
}
// All of the generic options require restart
// Some options don't require restart as those components handle it fine
// by themselves.
from.Options.URAccepted = to.Options.URAccepted
from.Options.URUniqueID = to.Options.URUniqueID
// All of the other generic options require restart. Or at least they may;
// removing this check requires going through those options carefully and
// making sure there are individual services that handle them correctly.
// This code is the "original" requires-restart check and protects other
// components that haven't yet been converted to VerifyConfig/CommitConfig
// handling.
if !reflect.DeepEqual(from.Options, to.Options) {
l.Debugln(m, "requires restart, options differ")
return false
+2 -2
View File
@@ -87,7 +87,7 @@ type rwFolder struct {
ignorePerms bool
copiers int
pullers int
shortID uint64
shortID protocol.ShortID
order config.PullOrder
maxConflicts int
sleep time.Duration
@@ -108,7 +108,7 @@ type rwFolder struct {
errorsMut sync.Mutex
}
func newRWFolder(m *Model, shortID uint64, cfg config.FolderConfiguration) *rwFolder {
func newRWFolder(m *Model, shortID protocol.ShortID, cfg config.FolderConfiguration) *rwFolder {
p := &rwFolder{
stateTracker: stateTracker{
folder: cfg.ID,
+1 -1
View File
@@ -13,7 +13,7 @@ import "syscall"
// MaximizeOpenFileLimit tries to set the resoure limit RLIMIT_NOFILE (number
// of open file descriptors) to the max (hard limit), if the current (soft
// limit) is below the max. Returns the new (though possibly unchanged) limit,
// or an error if it was could not be changed.
// or an error if it could not be changed.
func MaximizeOpenFileLimit() (int, error) {
// Get the current limit on number of open files.
var lim syscall.Rlimit
+9 -2
View File
@@ -16,6 +16,7 @@ import (
)
type DeviceID [32]byte
type ShortID uint64
var LocalDeviceID = DeviceID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
@@ -69,14 +70,20 @@ func (n DeviceID) Equals(other DeviceID) bool {
}
// Short returns an integer representing bits 0-63 of the device ID.
func (n DeviceID) Short() uint64 {
return binary.BigEndian.Uint64(n[:])
func (n DeviceID) Short() ShortID {
return ShortID(binary.BigEndian.Uint64(n[:]))
}
func (n *DeviceID) MarshalText() ([]byte, error) {
return []byte(n.String()), nil
}
func (s ShortID) String() string {
var bs [8]byte
binary.BigEndian.PutUint64(bs[:], uint64(s))
return base32.StdEncoding.EncodeToString(bs[:])[:7]
}
func (n *DeviceID) UnmarshalText(bs []byte) error {
id := string(bs)
id = strings.Trim(id, "=")
+22
View File
@@ -74,3 +74,25 @@ func TestMarshallingDeviceID(t *testing.T) {
t.Error("Compare error")
}
}
func TestShortIDString(t *testing.T) {
id, _ := DeviceIDFromString(formatted)
sid := id.Short().String()
if len(sid) != 7 {
t.Errorf("Wrong length for short ID: got %d, want 7", len(sid))
}
want := formatted[:len(sid)]
if sid != want {
t.Errorf("Wrong short ID: got %q, want %q", sid, want)
}
}
func TestDeviceIDFromBytes(t *testing.T) {
id0, _ := DeviceIDFromString(formatted)
id1 := DeviceIDFromBytes(id0[:])
if id1.String() != formatted {
t.Errorf("Wrong device ID, got %q, want %q", id1, formatted)
}
}
+65 -1
View File
@@ -36,7 +36,7 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
func TestHeaderFunctions(t *testing.T) {
func TestHeaderEncodeDecode(t *testing.T) {
f := func(ver, id, typ int) bool {
ver = int(uint(ver) % 16)
id = int(uint(id) % 4096)
@@ -50,6 +50,26 @@ func TestHeaderFunctions(t *testing.T) {
}
}
func TestHeaderMarshalUnmarshal(t *testing.T) {
f := func(ver, id, typ int) bool {
ver = int(uint(ver) % 16)
id = int(uint(id) % 4096)
typ = int(uint(typ) % 256)
buf := new(bytes.Buffer)
xw := xdr.NewWriter(buf)
h0 := header{version: ver, msgID: id, msgType: typ}
h0.encodeXDR(xw)
xr := xdr.NewReader(buf)
var h1 header
h1.decodeXDR(xr)
return h0 == h1
}
if err := quick.Check(f, nil); err != nil {
t.Error(err)
}
}
func TestHeaderLayout(t *testing.T) {
var e, a uint32
@@ -321,3 +341,47 @@ func timeoutWriteHeader(w *xdr.Writer, hdr header) {
case <-time.After(250 * time.Millisecond):
}
}
func TestFileInfoSize(t *testing.T) {
fi := FileInfo{
Blocks: []BlockInfo{
{Size: 42},
{Offset: 42, Size: 23},
{Offset: 42 + 23, Size: 34},
},
}
size := fi.Size()
want := int64(42 + 23 + 34)
if size != want {
t.Errorf("Incorrect size reported, got %d, want %d", size, want)
}
size = fi.Size() // Cached, this time
if size != want {
t.Errorf("Incorrect cached size reported, got %d, want %d", size, want)
}
fi.CachedSize = 8
want = 8
size = fi.Size() // Ensure it came from the cache
if size != want {
t.Errorf("Incorrect cached size reported, got %d, want %d", size, want)
}
fi.CachedSize = 0
fi.Flags = FlagDirectory
want = 128
size = fi.Size() // Directories are 128 bytes large
if size != want {
t.Errorf("Incorrect cached size reported, got %d, want %d", size, want)
}
fi.CachedSize = 0
fi.Flags = FlagDeleted
want = 128
size = fi.Size() // Also deleted files
if size != want {
t.Errorf("Incorrect cached size reported, got %d, want %d", size, want)
}
}
+7 -7
View File
@@ -10,31 +10,31 @@ type Vector []Counter
// Counter represents a single counter in the version vector.
type Counter struct {
ID uint64
ID ShortID
Value uint64
}
// Update returns a Vector with the index for the specific ID incremented by
// one. If it is possible, the vector v is updated and returned. If it is not,
// a copy will be created, updated and returned.
func (v Vector) Update(ID uint64) Vector {
func (v Vector) Update(id ShortID) Vector {
for i := range v {
if v[i].ID == ID {
if v[i].ID == id {
// Update an existing index
v[i].Value++
return v
} else if v[i].ID > ID {
} else if v[i].ID > id {
// Insert a new index
nv := make(Vector, len(v)+1)
copy(nv, v[:i])
nv[i].ID = ID
nv[i].ID = id
nv[i].Value = 1
copy(nv[i+1:], v[i:])
return nv
}
}
// Append a new index
return append(v, Counter{ID, 1})
return append(v, Counter{id, 1})
}
// Merge returns the vector containing the maximum indexes from v and b. If it
@@ -105,7 +105,7 @@ func (v Vector) Concurrent(b Vector) bool {
}
// Counter returns the current value of the given counter ID.
func (v Vector) Counter(id uint64) uint64 {
func (v Vector) Counter(id ShortID) uint64 {
for _, c := range v {
if c.ID == id {
return c.Value
+2 -2
View File
@@ -21,7 +21,7 @@ type xdrReader interface {
func (v Vector) EncodeXDRInto(w xdrWriter) (int, error) {
w.WriteUint32(uint32(len(v)))
for i := range v {
w.WriteUint64(v[i].ID)
w.WriteUint64(uint64(v[i].ID))
w.WriteUint64(v[i].Value)
}
return 4 + 16*len(v), nil
@@ -35,7 +35,7 @@ func (v *Vector) DecodeXDRFrom(r xdrReader) error {
}
n := make(Vector, l)
for i := range n {
n[i].ID = r.ReadUint64()
n[i].ID = ShortID(r.ReadUint64())
n[i].Value = r.ReadUint64()
}
*v = n
+1 -1
View File
@@ -69,7 +69,7 @@ type Walker struct {
// Number of routines to use for hashing
Hashers int
// Our vector clock id
ShortID uint64
ShortID protocol.ShortID
// Optional progress tick interval which defines how often FolderScanProgress
// events are emitted. Negative number means disabled.
ProgressTickIntervalS int
+1 -1
View File
@@ -56,7 +56,7 @@ func FetchLatestReleases(releasesURL, version string) []Release {
return nil
}
if resp.StatusCode > 299 {
l.Infoln("API call returned HTTP error: %s", resp.Status)
l.Infoln("API call returned HTTP error:", resp.Status)
return nil
}