mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
use atomicfile for safer writes
for now, allow daemon and client to both hit config
This commit is contained in:
parent
aacf871955
commit
9700d2f94b
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
@ -68,6 +68,10 @@
|
||||
"ImportPath": "github.com/dustin/go-humanize",
|
||||
"Rev": "b198514c204f20799b91c93b6ffd8b26be04c2c9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/facebookgo/atomicfile",
|
||||
"Rev": "6f117f2e7f224fb03eb5e5fba370eade6e2b90c8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/facebookgo/stack",
|
||||
"Rev": "4da6d991fc3c389efa512151354d643eb5fae4e2"
|
||||
|
||||
24
Godeps/_workspace/src/github.com/facebookgo/atomicfile/.travis.yml
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/facebookgo/atomicfile/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
- go get -v code.google.com/p/go.tools/cmd/vet
|
||||
- go get -v github.com/golang/lint/golint
|
||||
- go get -v code.google.com/p/go.tools/cmd/cover
|
||||
|
||||
install:
|
||||
- go install -race -v std
|
||||
- go get -race -t -v ./...
|
||||
- go install -race -v ./...
|
||||
|
||||
script:
|
||||
- go vet ./...
|
||||
- $HOME/gopath/bin/golint .
|
||||
- go test -cpu=2 -race -v ./...
|
||||
- go test -cpu=2 -covermode=atomic ./...
|
||||
54
Godeps/_workspace/src/github.com/facebookgo/atomicfile/atomicfile.go
generated
vendored
Normal file
54
Godeps/_workspace/src/github.com/facebookgo/atomicfile/atomicfile.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
// Package atomicfile provides the ability to write a file with an eventual
|
||||
// rename on Close. This allows for a file to always be in a consistent state
|
||||
// and never represent an in-progress write.
|
||||
package atomicfile
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// File behaves like os.File, but does an atomic rename operation at Close.
|
||||
type File struct {
|
||||
*os.File
|
||||
path string
|
||||
}
|
||||
|
||||
// New creates a new temporary file that will replace the file at the given
|
||||
// path when Closed.
|
||||
func New(path string, mode os.FileMode) (*File, error) {
|
||||
f, err := ioutil.TempFile(filepath.Dir(path), filepath.Base(path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.Chmod(f.Name(), mode); err != nil {
|
||||
os.Remove(f.Name())
|
||||
return nil, err
|
||||
}
|
||||
return &File{File: f, path: path}, nil
|
||||
}
|
||||
|
||||
// Close the file replacing the configured file.
|
||||
func (f *File) Close() error {
|
||||
if err := f.File.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Rename(f.Name(), f.path); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Abort closes the file and removes it instead of replacing the configured
|
||||
// file. This is useful if after starting to write to the file you decide you
|
||||
// don't want it anymore.
|
||||
func (f *File) Abort() error {
|
||||
if err := f.File.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Remove(f.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
86
Godeps/_workspace/src/github.com/facebookgo/atomicfile/atomicfile_test.go
generated
vendored
Normal file
86
Godeps/_workspace/src/github.com/facebookgo/atomicfile/atomicfile_test.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
package atomicfile_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/facebookgo/atomicfile"
|
||||
)
|
||||
|
||||
func test(t *testing.T, dir, prefix string) {
|
||||
t.Parallel()
|
||||
|
||||
tmpfile, err := ioutil.TempFile(dir, prefix)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
name := tmpfile.Name()
|
||||
|
||||
if err := os.Remove(name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer os.Remove(name)
|
||||
f, err := atomicfile.New(name, os.FileMode(0666))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Write([]byte("foo"))
|
||||
if _, err := os.Stat(name); !os.IsNotExist(err) {
|
||||
t.Fatal("did not expect file to exist")
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("expected file to exist: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentDir(t *testing.T) {
|
||||
cwd, _ := os.Getwd()
|
||||
test(t, cwd, "atomicfile-current-dir-")
|
||||
}
|
||||
|
||||
func TestRootTmpDir(t *testing.T) {
|
||||
test(t, "/tmp", "atomicfile-root-tmp-dir-")
|
||||
}
|
||||
|
||||
func TestDefaultTmpDir(t *testing.T) {
|
||||
test(t, "", "atomicfile-default-tmp-dir-")
|
||||
}
|
||||
|
||||
func TestAbort(t *testing.T) {
|
||||
contents := []byte("the answer is 42")
|
||||
t.Parallel()
|
||||
tmpfile, err := ioutil.TempFile("", "atomicfile-abort-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
name := tmpfile.Name()
|
||||
if _, err := tmpfile.Write(contents); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(name)
|
||||
|
||||
f, err := atomicfile.New(name, os.FileMode(0666))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Write([]byte("foo"))
|
||||
if err := f.Abort(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
t.Fatalf("expected file to exist: %s", err)
|
||||
}
|
||||
actual, err := ioutil.ReadFile(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(contents, actual) {
|
||||
t.Fatalf(`did not find expected "%s" instead found "%s"`, contents, actual)
|
||||
}
|
||||
}
|
||||
30
Godeps/_workspace/src/github.com/facebookgo/atomicfile/license
generated
vendored
Normal file
30
Godeps/_workspace/src/github.com/facebookgo/atomicfile/license
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
BSD License
|
||||
|
||||
For atomicfile software
|
||||
|
||||
Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name Facebook nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
23
Godeps/_workspace/src/github.com/facebookgo/atomicfile/patents
generated
vendored
Normal file
23
Godeps/_workspace/src/github.com/facebookgo/atomicfile/patents
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
Additional Grant of Patent Rights
|
||||
|
||||
"Software" means the atomicfile software distributed by Facebook, Inc.
|
||||
|
||||
Facebook hereby grants you a perpetual, worldwide, royalty-free, non-exclusive,
|
||||
irrevocable (subject to the termination provision below) license under any
|
||||
rights in any patent claims owned by Facebook, to make, have made, use, sell,
|
||||
offer to sell, import, and otherwise transfer the Software. For avoidance of
|
||||
doubt, no license is granted under Facebook’s rights in any patent claims that
|
||||
are infringed by (i) modifications to the Software made by you or a third party,
|
||||
or (ii) the Software in combination with any software or other technology
|
||||
provided by you or a third party.
|
||||
|
||||
The license granted hereunder will terminate, automatically and without notice,
|
||||
for anyone that makes any claim (including by filing any lawsuit, assertion or
|
||||
other action) alleging (a) direct, indirect, or contributory infringement or
|
||||
inducement to infringe any patent: (i) by Facebook or any of its subsidiaries or
|
||||
affiliates, whether or not such claim is related to the Software, (ii) by any
|
||||
party if such claim arises in whole or in part from any software, product or
|
||||
service of Facebook or any of its subsidiaries or affiliates, whether or not
|
||||
such claim is related to the Software, or (iii) by any party relating to the
|
||||
Software; or (b) that any right in any patent claim of Facebook is invalid or
|
||||
unenforceable.
|
||||
4
Godeps/_workspace/src/github.com/facebookgo/atomicfile/readme.md
generated
vendored
Normal file
4
Godeps/_workspace/src/github.com/facebookgo/atomicfile/readme.md
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
atomicfile [](http://travis-ci.org/facebookgo/atomicfile)
|
||||
==========
|
||||
|
||||
Documentation: http://godoc.org/github.com/facebookgo/atomicfile
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/facebookgo/atomicfile"
|
||||
"github.com/jbenet/go-ipfs/repo/config"
|
||||
"github.com/jbenet/go-ipfs/util"
|
||||
"github.com/jbenet/go-ipfs/util/debugerror"
|
||||
@ -34,7 +35,7 @@ func writeConfigFile(filename string, cfg interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.Create(filename)
|
||||
f, err := atomicfile.New(filename, 0775)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user