Commit d65a5cce authored by Robert Griesemer's avatar Robert Griesemer

1) Change default gofmt default settings for

   parsing and printing to new syntax.

   Use -oldparser to parse the old syntax,
   use -oldprinter to print the old syntax.

2) Change default gofmt formatting settings
   to use tabs for indentation only and to use
   spaces for alignment. This will make the code
   alignment insensitive to an editor's tabwidth.

   Use -spaces=false to use tabs for alignment.

3) Manually changed src/exp/parser/parser_test.go
   so that it doesn't try to parse the parser's
   source files using the old syntax (they have
   new syntax now).

4) gofmt -w src misc test/bench

4th set of files.

R=rsc
CC=golang-dev
https://golang.org/cl/180049
parent a3d1045f
...@@ -9,8 +9,8 @@ package once ...@@ -9,8 +9,8 @@ package once
import "sync" import "sync"
type job struct { type job struct {
done bool; done bool
sync.Mutex; // should probably be sync.Notification or some such sync.Mutex // should probably be sync.Notification or some such
} }
var jobs = make(map[func()]*job) var jobs = make(map[func()]*job)
...@@ -37,23 +37,23 @@ var joblock sync.Mutex ...@@ -37,23 +37,23 @@ var joblock sync.Mutex
// because the func() expression in the first creates a new // because the func() expression in the first creates a new
// func each time f runs, and each of those funcs is run once. // func each time f runs, and each of those funcs is run once.
func Do(f func()) { func Do(f func()) {
joblock.Lock(); joblock.Lock()
j, present := jobs[f]; j, present := jobs[f]
if !present { if !present {
// run it // run it
j = new(job); j = new(job)
j.Lock(); j.Lock()
jobs[f] = j; jobs[f] = j
joblock.Unlock(); joblock.Unlock()
f(); f()
j.done = true; j.done = true
j.Unlock(); j.Unlock()
} else { } else {
// wait for it // wait for it
joblock.Unlock(); joblock.Unlock()
if j.done != true { if j.done != true {
j.Lock(); j.Lock()
j.Unlock(); j.Unlock()
} }
} }
} }
...@@ -5,25 +5,25 @@ ...@@ -5,25 +5,25 @@
package once_test package once_test
import ( import (
"once"; "once"
"testing"; "testing"
) )
var ncall int var ncall int
func call() { ncall++ } func call() { ncall++ }
func TestDo(t *testing.T) { func TestDo(t *testing.T) {
ncall = 0; ncall = 0
once.Do(call); once.Do(call)
if ncall != 1 { if ncall != 1 {
t.Fatalf("once.Do(call) didn't call(): ncall=%d", ncall) t.Fatalf("once.Do(call) didn't call(): ncall=%d", ncall)
} }
once.Do(call); once.Do(call)
if ncall != 1 { if ncall != 1 {
t.Fatalf("second once.Do(call) did call(): ncall=%d", ncall) t.Fatalf("second once.Do(call) did call(): ncall=%d", ncall)
} }
once.Do(call); once.Do(call)
if ncall != 1 { if ncall != 1 {
t.Fatalf("third once.Do(call) did call(): ncall=%d", ncall) t.Fatalf("third once.Do(call) did call(): ncall=%d", ncall)
} }
......
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
// Readdirnames reads the contents of the directory associated with file and // Readdirnames reads the contents of the directory associated with file and
...@@ -21,59 +21,59 @@ const ( ...@@ -21,59 +21,59 @@ const (
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.bufp = 0; d.bufp = 0
// Final argument is (basep *uintptr) and the syscall doesn't take nil. // Final argument is (basep *uintptr) and the syscall doesn't take nil.
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr)); d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr))
if errno != 0 { if errno != 0 {
d.nbuf = 0; d.nbuf = 0
return names, NewSyscallError("getdirentries", errno); return names, NewSyscallError("getdirentries", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
if dirent.Reclen == 0 { if dirent.Reclen == 0 {
d.bufp = d.nbuf; d.bufp = d.nbuf
break; break
} }
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Ino == 0 { // File absent in directory. if dirent.Ino == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:dirent.Namlen]); var name = string(bytes[0:dirent.Namlen])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }
...@@ -5,70 +5,70 @@ ...@@ -5,70 +5,70 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.bufp = 0; d.bufp = 0
// Final argument is (basep *uintptr) and the syscall doesn't take nil. // Final argument is (basep *uintptr) and the syscall doesn't take nil.
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr)); d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr))
if errno != 0 { if errno != 0 {
d.nbuf = 0; d.nbuf = 0
return names, NewSyscallError("getdirentries", errno); return names, NewSyscallError("getdirentries", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
if dirent.Reclen == 0 { if dirent.Reclen == 0 {
d.bufp = d.nbuf; d.bufp = d.nbuf
break; break
} }
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Fileno == 0 { // File absent in directory. if dirent.Fileno == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:dirent.Namlen]); var name = string(bytes[0:dirent.Namlen])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
func clen(n []byte) int { func clen(n []byte) int {
...@@ -19,59 +19,59 @@ func clen(n []byte) int { ...@@ -19,59 +19,59 @@ func clen(n []byte) int {
return i return i
} }
} }
return len(n); return len(n)
} }
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.nbuf, errno = syscall.Getdents(file.fd, d.buf); d.nbuf, errno = syscall.Getdents(file.fd, d.buf)
if errno != 0 { if errno != 0 {
return names, NewSyscallError("getdents", errno) return names, NewSyscallError("getdents", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
d.bufp = 0; d.bufp = 0
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Ino == 0 { // File absent in directory. if dirent.Ino == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:clen(bytes)]); var name = string(bytes[0:clen(bytes)])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
package os package os
import ( import (
"syscall"; "syscall"
"unsafe"; "unsafe"
) )
const ( const (
blockSize = 4096; // TODO(r): use statfs blockSize = 4096 // TODO(r): use statfs
) )
func clen(n []byte) int { func clen(n []byte) int {
...@@ -19,59 +19,59 @@ func clen(n []byte) int { ...@@ -19,59 +19,59 @@ func clen(n []byte) int {
return i return i
} }
} }
return len(n); return len(n)
} }
func (file *File) Readdirnames(count int) (names []string, err Error) { func (file *File) Readdirnames(count int) (names []string, err Error) {
// If this file has no dirinfo, create one. // If this file has no dirinfo, create one.
if file.dirinfo == nil { if file.dirinfo == nil {
file.dirinfo = new(dirInfo); file.dirinfo = new(dirInfo)
// The buffer must be at least a block long. // The buffer must be at least a block long.
// TODO(r): use fstatfs to find fs block size. // TODO(r): use fstatfs to find fs block size.
file.dirinfo.buf = make([]byte, blockSize); file.dirinfo.buf = make([]byte, blockSize)
} }
d := file.dirinfo; d := file.dirinfo
size := count; size := count
if size < 0 { if size < 0 {
size = 100 size = 100
} }
names = make([]string, 0, size); // Empty with room to grow. names = make([]string, 0, size) // Empty with room to grow.
for count != 0 { for count != 0 {
// Refill the buffer if necessary // Refill the buffer if necessary
if d.bufp >= d.nbuf { if d.bufp >= d.nbuf {
var errno int; var errno int
d.nbuf, errno = syscall.Getdents(file.fd, d.buf); d.nbuf, errno = syscall.Getdents(file.fd, d.buf)
if errno != 0 { if errno != 0 {
return names, NewSyscallError("getdents", errno) return names, NewSyscallError("getdents", errno)
} }
if d.nbuf <= 0 { if d.nbuf <= 0 {
break // EOF break // EOF
} }
d.bufp = 0; d.bufp = 0
} }
// Drain the buffer // Drain the buffer
for count != 0 && d.bufp < d.nbuf { for count != 0 && d.bufp < d.nbuf {
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
d.bufp += int(dirent.Reclen); d.bufp += int(dirent.Reclen)
if dirent.Ino == 0 { // File absent in directory. if dirent.Ino == 0 { // File absent in directory.
continue continue
} }
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
var name = string(bytes[0:clen(bytes)]); var name = string(bytes[0:clen(bytes)])
if name == "." || name == ".." { // Useless names if name == "." || name == ".." { // Useless names
continue continue
} }
count--; count--
if len(names) == cap(names) { if len(names) == cap(names) {
nnames := make([]string, len(names), 2*len(names)); nnames := make([]string, len(names), 2*len(names))
for i := 0; i < len(names); i++ { for i := 0; i < len(names); i++ {
nnames[i] = names[i] nnames[i] = names[i]
} }
names = nnames; names = nnames
} }
names = names[0 : len(names)+1]; names = names[0 : len(names)+1]
names[len(names)-1] = name; names[len(names)-1] = name
} }
} }
return names, nil; return names, nil
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
package os package os
import ( import (
"once"; "once"
) )
// ENOENV is the Error indicating that an environment variable does not exist. // ENOENV is the Error indicating that an environment variable does not exist.
...@@ -17,12 +17,12 @@ var env map[string]string ...@@ -17,12 +17,12 @@ var env map[string]string
func copyenv() { func copyenv() {
env = make(map[string]string); env = make(map[string]string)
for _, s := range Envs { for _, s := range Envs {
for j := 0; j < len(s); j++ { for j := 0; j < len(s); j++ {
if s[j] == '=' { if s[j] == '=' {
env[s[0:j]] = s[j+1:]; env[s[0:j]] = s[j+1:]
break; break
} }
} }
} }
...@@ -31,56 +31,56 @@ func copyenv() { ...@@ -31,56 +31,56 @@ func copyenv() {
// Getenverror retrieves the value of the environment variable named by the key. // Getenverror retrieves the value of the environment variable named by the key.
// It returns the value and an error, if any. // It returns the value and an error, if any.
func Getenverror(key string) (value string, err Error) { func Getenverror(key string) (value string, err Error) {
once.Do(copyenv); once.Do(copyenv)
if len(key) == 0 { if len(key) == 0 {
return "", EINVAL return "", EINVAL
} }
v, ok := env[key]; v, ok := env[key]
if !ok { if !ok {
return "", ENOENV return "", ENOENV
} }
return v, nil; return v, nil
} }
// Getenv retrieves the value of the environment variable named by the key. // Getenv retrieves the value of the environment variable named by the key.
// It returns the value, which will be empty if the variable is not present. // It returns the value, which will be empty if the variable is not present.
func Getenv(key string) string { func Getenv(key string) string {
v, _ := Getenverror(key); v, _ := Getenverror(key)
return v; return v
} }
// Setenv sets the value of the environment variable named by the key. // Setenv sets the value of the environment variable named by the key.
// It returns an Error, if any. // It returns an Error, if any.
func Setenv(key, value string) Error { func Setenv(key, value string) Error {
once.Do(copyenv); once.Do(copyenv)
if len(key) == 0 { if len(key) == 0 {
return EINVAL return EINVAL
} }
env[key] = value; env[key] = value
return nil; return nil
} }
// Clearenv deletes all environment variables. // Clearenv deletes all environment variables.
func Clearenv() { func Clearenv() {
once.Do(copyenv); // prevent copyenv in Getenv/Setenv once.Do(copyenv) // prevent copyenv in Getenv/Setenv
env = make(map[string]string); env = make(map[string]string)
} }
// Environ returns an array of strings representing the environment, // Environ returns an array of strings representing the environment,
// in the form "key=value". // in the form "key=value".
func Environ() []string { func Environ() []string {
once.Do(copyenv); once.Do(copyenv)
a := make([]string, len(env)); a := make([]string, len(env))
i := 0; i := 0
for k, v := range env { for k, v := range env {
// check i < len(a) for safety, // check i < len(a) for safety,
// in case env is changing underfoot. // in case env is changing underfoot.
if i < len(a) { if i < len(a) {
a[i] = k + "=" + v; a[i] = k + "=" + v
i++; i++
} }
} }
return a[0:i]; return a[0:i]
} }
...@@ -8,85 +8,85 @@ import syscall "syscall" ...@@ -8,85 +8,85 @@ import syscall "syscall"
// An Error can represent any printable error condition. // An Error can represent any printable error condition.
type Error interface { type Error interface {
String() string; String() string
} }
// A helper type that can be embedded or wrapped to simplify satisfying // A helper type that can be embedded or wrapped to simplify satisfying
// Error. // Error.
type ErrorString string type ErrorString string
func (e ErrorString) String() string { return string(e) } func (e ErrorString) String() string { return string(e) }
// Note: If the name of the function NewError changes, // Note: If the name of the function NewError changes,
// pkg/go/doc/doc.go should be adjusted since it hardwires // pkg/go/doc/doc.go should be adjusted since it hardwires
// this name in a heuristic. // this name in a heuristic.
// NewError converts s to an ErrorString, which satisfies the Error interface. // NewError converts s to an ErrorString, which satisfies the Error interface.
func NewError(s string) Error { return ErrorString(s) } func NewError(s string) Error { return ErrorString(s) }
// Errno is the Unix error number. Names such as EINVAL are simple // Errno is the Unix error number. Names such as EINVAL are simple
// wrappers to convert the error number into an Error. // wrappers to convert the error number into an Error.
type Errno int64 type Errno int64
func (e Errno) String() string { return syscall.Errstr(int(e)) } func (e Errno) String() string { return syscall.Errstr(int(e)) }
// Commonly known Unix errors. // Commonly known Unix errors.
var ( var (
EPERM Error = Errno(syscall.EPERM); EPERM Error = Errno(syscall.EPERM)
ENOENT Error = Errno(syscall.ENOENT); ENOENT Error = Errno(syscall.ENOENT)
ESRCH Error = Errno(syscall.ESRCH); ESRCH Error = Errno(syscall.ESRCH)
EINTR Error = Errno(syscall.EINTR); EINTR Error = Errno(syscall.EINTR)
EIO Error = Errno(syscall.EIO); EIO Error = Errno(syscall.EIO)
ENXIO Error = Errno(syscall.ENXIO); ENXIO Error = Errno(syscall.ENXIO)
E2BIG Error = Errno(syscall.E2BIG); E2BIG Error = Errno(syscall.E2BIG)
ENOEXEC Error = Errno(syscall.ENOEXEC); ENOEXEC Error = Errno(syscall.ENOEXEC)
EBADF Error = Errno(syscall.EBADF); EBADF Error = Errno(syscall.EBADF)
ECHILD Error = Errno(syscall.ECHILD); ECHILD Error = Errno(syscall.ECHILD)
EDEADLK Error = Errno(syscall.EDEADLK); EDEADLK Error = Errno(syscall.EDEADLK)
ENOMEM Error = Errno(syscall.ENOMEM); ENOMEM Error = Errno(syscall.ENOMEM)
EACCES Error = Errno(syscall.EACCES); EACCES Error = Errno(syscall.EACCES)
EFAULT Error = Errno(syscall.EFAULT); EFAULT Error = Errno(syscall.EFAULT)
EBUSY Error = Errno(syscall.EBUSY); EBUSY Error = Errno(syscall.EBUSY)
EEXIST Error = Errno(syscall.EEXIST); EEXIST Error = Errno(syscall.EEXIST)
EXDEV Error = Errno(syscall.EXDEV); EXDEV Error = Errno(syscall.EXDEV)
ENODEV Error = Errno(syscall.ENODEV); ENODEV Error = Errno(syscall.ENODEV)
ENOTDIR Error = Errno(syscall.ENOTDIR); ENOTDIR Error = Errno(syscall.ENOTDIR)
EISDIR Error = Errno(syscall.EISDIR); EISDIR Error = Errno(syscall.EISDIR)
EINVAL Error = Errno(syscall.EINVAL); EINVAL Error = Errno(syscall.EINVAL)
ENFILE Error = Errno(syscall.ENFILE); ENFILE Error = Errno(syscall.ENFILE)
EMFILE Error = Errno(syscall.EMFILE); EMFILE Error = Errno(syscall.EMFILE)
ENOTTY Error = Errno(syscall.ENOTTY); ENOTTY Error = Errno(syscall.ENOTTY)
EFBIG Error = Errno(syscall.EFBIG); EFBIG Error = Errno(syscall.EFBIG)
ENOSPC Error = Errno(syscall.ENOSPC); ENOSPC Error = Errno(syscall.ENOSPC)
ESPIPE Error = Errno(syscall.ESPIPE); ESPIPE Error = Errno(syscall.ESPIPE)
EROFS Error = Errno(syscall.EROFS); EROFS Error = Errno(syscall.EROFS)
EMLINK Error = Errno(syscall.EMLINK); EMLINK Error = Errno(syscall.EMLINK)
EPIPE Error = Errno(syscall.EPIPE); EPIPE Error = Errno(syscall.EPIPE)
EAGAIN Error = Errno(syscall.EAGAIN); EAGAIN Error = Errno(syscall.EAGAIN)
EDOM Error = Errno(syscall.EDOM); EDOM Error = Errno(syscall.EDOM)
ERANGE Error = Errno(syscall.ERANGE); ERANGE Error = Errno(syscall.ERANGE)
EADDRINUSE Error = Errno(syscall.EADDRINUSE); EADDRINUSE Error = Errno(syscall.EADDRINUSE)
ECONNREFUSED Error = Errno(syscall.ECONNREFUSED); ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG); ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT); EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
) )
// PathError records an error and the operation and file path that caused it. // PathError records an error and the operation and file path that caused it.
type PathError struct { type PathError struct {
Op string; Op string
Path string; Path string
Error Error; Error Error
} }
func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() } func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
// SyscallError records an error from a specific system call. // SyscallError records an error from a specific system call.
type SyscallError struct { type SyscallError struct {
Syscall string; Syscall string
Errno Errno; Errno Errno
} }
func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() } func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
// Note: If the name of the function NewSyscallError changes, // Note: If the name of the function NewSyscallError changes,
// pkg/go/doc/doc.go should be adjusted since it hardwires // pkg/go/doc/doc.go should be adjusted since it hardwires
...@@ -99,5 +99,5 @@ func NewSyscallError(syscall string, errno int) Error { ...@@ -99,5 +99,5 @@ func NewSyscallError(syscall string, errno int) Error {
if errno == 0 { if errno == 0 {
return nil return nil
} }
return &SyscallError{syscall, Errno(errno)}; return &SyscallError{syscall, Errno(errno)}
} }
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package os package os
import ( import (
"syscall"; "syscall"
) )
// ForkExec forks the current process and invokes Exec with the file, arguments, // ForkExec forks the current process and invokes Exec with the file, arguments,
...@@ -17,7 +17,7 @@ import ( ...@@ -17,7 +17,7 @@ import (
// If dir is not empty, the child chdirs into the directory before execing the program. // If dir is not empty, the child chdirs into the directory before execing the program.
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) { func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
// Create array of integer (system) fds. // Create array of integer (system) fds.
intfd := make([]int, len(fd)); intfd := make([]int, len(fd))
for i, f := range fd { for i, f := range fd {
if f == nil { if f == nil {
intfd[i] = -1 intfd[i] = -1
...@@ -26,11 +26,11 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File ...@@ -26,11 +26,11 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File
} }
} }
p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd); p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd)
if e != 0 { if e != 0 {
return 0, &PathError{"fork/exec", argv0, Errno(e)} return 0, &PathError{"fork/exec", argv0, Errno(e)}
} }
return p, nil; return p, nil
} }
// Exec replaces the current process with an execution of the program // Exec replaces the current process with an execution of the program
...@@ -41,11 +41,11 @@ func Exec(argv0 string, argv []string, envv []string) Error { ...@@ -41,11 +41,11 @@ func Exec(argv0 string, argv []string, envv []string) Error {
if envv == nil { if envv == nil {
envv = Environ() envv = Environ()
} }
e := syscall.Exec(argv0, argv, envv); e := syscall.Exec(argv0, argv, envv)
if e != 0 { if e != 0 {
return &PathError{"exec", argv0, Errno(e)} return &PathError{"exec", argv0, Errno(e)}
} }
return nil; return nil
} }
// TODO(rsc): Should os implement its own syscall.WaitStatus // TODO(rsc): Should os implement its own syscall.WaitStatus
...@@ -57,17 +57,17 @@ func Exec(argv0 string, argv []string, envv []string) Error { ...@@ -57,17 +57,17 @@ func Exec(argv0 string, argv []string, envv []string) Error {
// Waitmsg stores the information about an exited process as reported by Wait. // Waitmsg stores the information about an exited process as reported by Wait.
type Waitmsg struct { type Waitmsg struct {
Pid int; // The process's id. Pid int // The process's id.
syscall.WaitStatus; // System-dependent status info. syscall.WaitStatus // System-dependent status info.
Rusage *syscall.Rusage; // System-dependent resource usage info. Rusage *syscall.Rusage // System-dependent resource usage info.
} }
// Options for Wait. // Options for Wait.
const ( const (
WNOHANG = syscall.WNOHANG; // Don't wait if no process has exited. WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
WSTOPPED = syscall.WSTOPPED; // If set, status of stopped subprocesses is also reported. WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
WUNTRACED = WSTOPPED; WUNTRACED = WSTOPPED
WRUSAGE = 1 << 20; // Record resource usage. WRUSAGE = 1 << 20 // Record resource usage.
) )
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's // WRUSAGE must not be too high a bit, to avoid clashing with Linux's
...@@ -78,21 +78,21 @@ const ( ...@@ -78,21 +78,21 @@ const (
// Waitmsg describing its status and an Error, if any. The options // Waitmsg describing its status and an Error, if any. The options
// (WNOHANG etc.) affect the behavior of the Wait call. // (WNOHANG etc.) affect the behavior of the Wait call.
func Wait(pid int, options int) (w *Waitmsg, err Error) { func Wait(pid int, options int) (w *Waitmsg, err Error) {
var status syscall.WaitStatus; var status syscall.WaitStatus
var rusage *syscall.Rusage; var rusage *syscall.Rusage
if options&WRUSAGE != 0 { if options&WRUSAGE != 0 {
rusage = new(syscall.Rusage); rusage = new(syscall.Rusage)
options ^= WRUSAGE; options ^= WRUSAGE
} }
pid1, e := syscall.Wait4(pid, &status, options, rusage); pid1, e := syscall.Wait4(pid, &status, options, rusage)
if e != 0 { if e != 0 {
return nil, NewSyscallError("wait", e) return nil, NewSyscallError("wait", e)
} }
w = new(Waitmsg); w = new(Waitmsg)
w.Pid = pid1; w.Pid = pid1
w.WaitStatus = status; w.WaitStatus = status
w.Rusage = rusage; w.Rusage = rusage
return w, nil; return w, nil
} }
// Convert i to decimal string. // Convert i to decimal string.
...@@ -101,37 +101,37 @@ func itod(i int) string { ...@@ -101,37 +101,37 @@ func itod(i int) string {
return "0" return "0"
} }
u := uint64(i); u := uint64(i)
if i < 0 { if i < 0 {
u = -u u = -u
} }
// Assemble decimal in reverse order. // Assemble decimal in reverse order.
var b [32]byte; var b [32]byte
bp := len(b); bp := len(b)
for ; u > 0; u /= 10 { for ; u > 0; u /= 10 {
bp--; bp--
b[bp] = byte(u%10) + '0'; b[bp] = byte(u%10) + '0'
} }
if i < 0 { if i < 0 {
bp--; bp--
b[bp] = '-'; b[bp] = '-'
} }
return string(b[bp:]); return string(b[bp:])
} }
func (w Waitmsg) String() string { func (w Waitmsg) String() string {
// TODO(austin) Use signal names when possible? // TODO(austin) Use signal names when possible?
res := ""; res := ""
switch { switch {
case w.Exited(): case w.Exited():
res = "exit status " + itod(w.ExitStatus()) res = "exit status " + itod(w.ExitStatus())
case w.Signaled(): case w.Signaled():
res = "signal " + itod(w.Signal()) res = "signal " + itod(w.Signal())
case w.Stopped(): case w.Stopped():
res = "stop signal " + itod(w.StopSignal()); res = "stop signal " + itod(w.StopSignal())
if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 { if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
res += " (trap " + itod(w.TrapCause()) + ")" res += " (trap " + itod(w.TrapCause()) + ")"
} }
...@@ -141,11 +141,11 @@ func (w Waitmsg) String() string { ...@@ -141,11 +141,11 @@ func (w Waitmsg) String() string {
if w.CoreDump() { if w.CoreDump() {
res += " (core dumped)" res += " (core dumped)"
} }
return res; return res
} }
// Getpid returns the process id of the caller. // Getpid returns the process id of the caller.
func Getpid() int { return syscall.Getpid() } func Getpid() int { return syscall.Getpid() }
// Getppid returns the process id of the caller's parent. // Getppid returns the process id of the caller's parent.
func Getppid() int { return syscall.Getppid() } func Getppid() int { return syscall.Getppid() }
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package os package os
import ( import (
"syscall"; "syscall"
) )
// Getwd returns a rooted path name corresponding to the // Getwd returns a rooted path name corresponding to the
...@@ -15,21 +15,21 @@ import ( ...@@ -15,21 +15,21 @@ import (
func Getwd() (string, Error) { func Getwd() (string, Error) {
// If the operating system provides a Getwd call, use it. // If the operating system provides a Getwd call, use it.
if syscall.ImplementsGetwd { if syscall.ImplementsGetwd {
s, e := syscall.Getwd(); s, e := syscall.Getwd()
return s, NewSyscallError("getwd", e); return s, NewSyscallError("getwd", e)
} }
// Otherwise, we're trying to find our way back to ".". // Otherwise, we're trying to find our way back to ".".
dot, err := Stat("."); dot, err := Stat(".")
if err != nil { if err != nil {
return "", err return "", err
} }
// Clumsy but widespread kludge: // Clumsy but widespread kludge:
// if $PWD is set and matches ".", use it. // if $PWD is set and matches ".", use it.
pwd := Getenv("PWD"); pwd := Getenv("PWD")
if len(pwd) > 0 && pwd[0] == '/' { if len(pwd) > 0 && pwd[0] == '/' {
d, err := Stat(pwd); d, err := Stat(pwd)
if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino { if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino {
return pwd, nil return pwd, nil
} }
...@@ -37,7 +37,7 @@ func Getwd() (string, Error) { ...@@ -37,7 +37,7 @@ func Getwd() (string, Error) {
// Root is a special case because it has no parent // Root is a special case because it has no parent
// and ends in a slash. // and ends in a slash.
root, err := Stat("/"); root, err := Stat("/")
if err != nil { if err != nil {
// Can't stat root - no hope. // Can't stat root - no hope.
return "", err return "", err
...@@ -49,44 +49,44 @@ func Getwd() (string, Error) { ...@@ -49,44 +49,44 @@ func Getwd() (string, Error) {
// General algorithm: find name in parent // General algorithm: find name in parent
// and then find name of parent. Each iteration // and then find name of parent. Each iteration
// adds /name to the beginning of pwd. // adds /name to the beginning of pwd.
pwd = ""; pwd = ""
for parent := ".."; ; parent = "../" + parent { for parent := ".."; ; parent = "../" + parent {
if len(parent) >= 1024 { // Sanity check if len(parent) >= 1024 { // Sanity check
return "", ENAMETOOLONG return "", ENAMETOOLONG
} }
fd, err := Open(parent, O_RDONLY, 0); fd, err := Open(parent, O_RDONLY, 0)
if err != nil { if err != nil {
return "", err return "", err
} }
for { for {
names, err := fd.Readdirnames(100); names, err := fd.Readdirnames(100)
if err != nil { if err != nil {
fd.Close(); fd.Close()
return "", err; return "", err
} }
for _, name := range names { for _, name := range names {
d, _ := Lstat(parent + "/" + name); d, _ := Lstat(parent + "/" + name)
if d.Dev == dot.Dev && d.Ino == dot.Ino { if d.Dev == dot.Dev && d.Ino == dot.Ino {
pwd = "/" + name + pwd; pwd = "/" + name + pwd
goto Found; goto Found
} }
} }
} }
fd.Close(); fd.Close()
return "", ENOENT; return "", ENOENT
Found: Found:
pd, err := fd.Stat(); pd, err := fd.Stat()
if err != nil { if err != nil {
return "", err return "", err
} }
fd.Close(); fd.Close()
if pd.Dev == root.Dev && pd.Ino == root.Ino { if pd.Dev == root.Dev && pd.Ino == root.Ino {
break break
} }
// Set up for next round. // Set up for next round.
dot = pd; dot = pd
} }
return pwd, nil; return pwd, nil
} }
This diff is collapsed.
...@@ -14,45 +14,45 @@ package os ...@@ -14,45 +14,45 @@ package os
// and returns nil. // and returns nil.
func MkdirAll(path string, perm int) Error { func MkdirAll(path string, perm int) Error {
// If path exists, stop with success or error. // If path exists, stop with success or error.
dir, err := Lstat(path); dir, err := Lstat(path)
if err == nil { if err == nil {
if dir.IsDirectory() { if dir.IsDirectory() {
return nil return nil
} }
return &PathError{"mkdir", path, ENOTDIR}; return &PathError{"mkdir", path, ENOTDIR}
} }
// Doesn't already exist; make sure parent does. // Doesn't already exist; make sure parent does.
i := len(path); i := len(path)
for i > 0 && path[i-1] == '/' { // Skip trailing slashes. for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
i-- i--
} }
j := i; j := i
for j > 0 && path[j-1] != '/' { // Scan backward over element. for j > 0 && path[j-1] != '/' { // Scan backward over element.
j-- j--
} }
if j > 0 { if j > 0 {
// Create parent // Create parent
err = MkdirAll(path[0:j-1], perm); err = MkdirAll(path[0:j-1], perm)
if err != nil { if err != nil {
return err return err
} }
} }
// Now parent exists, try to create. // Now parent exists, try to create.
err = Mkdir(path, perm); err = Mkdir(path, perm)
if err != nil { if err != nil {
// Handle arguments like "foo/." by // Handle arguments like "foo/." by
// double-checking that directory doesn't exist. // double-checking that directory doesn't exist.
dir, err1 := Lstat(path); dir, err1 := Lstat(path)
if err1 == nil && dir.IsDirectory() { if err1 == nil && dir.IsDirectory() {
return nil return nil
} }
return err; return err
} }
return nil; return nil
} }
// RemoveAll removes path and any children it contains. // RemoveAll removes path and any children it contains.
...@@ -61,18 +61,18 @@ func MkdirAll(path string, perm int) Error { ...@@ -61,18 +61,18 @@ func MkdirAll(path string, perm int) Error {
// returns nil (no error). // returns nil (no error).
func RemoveAll(path string) Error { func RemoveAll(path string) Error {
// Simple case: if Remove works, we're done. // Simple case: if Remove works, we're done.
err := Remove(path); err := Remove(path)
if err == nil { if err == nil {
return nil return nil
} }
// Otherwise, is this a directory we need to recurse into? // Otherwise, is this a directory we need to recurse into?
dir, serr := Lstat(path); dir, serr := Lstat(path)
if serr != nil { if serr != nil {
if serr, ok := serr.(*PathError); ok && serr.Error == ENOENT { if serr, ok := serr.(*PathError); ok && serr.Error == ENOENT {
return nil return nil
} }
return serr; return serr
} }
if !dir.IsDirectory() { if !dir.IsDirectory() {
// Not a directory; return the error from Remove. // Not a directory; return the error from Remove.
...@@ -80,18 +80,18 @@ func RemoveAll(path string) Error { ...@@ -80,18 +80,18 @@ func RemoveAll(path string) Error {
} }
// Directory. // Directory.
fd, err := Open(path, O_RDONLY, 0); fd, err := Open(path, O_RDONLY, 0)
if err != nil { if err != nil {
return err return err
} }
defer fd.Close(); defer fd.Close()
// Remove contents & return first error. // Remove contents & return first error.
err = nil; err = nil
for { for {
names, err1 := fd.Readdirnames(100); names, err1 := fd.Readdirnames(100)
for _, name := range names { for _, name := range names {
err1 := RemoveAll(path + "/" + name); err1 := RemoveAll(path + "/" + name)
if err == nil { if err == nil {
err = err1 err = err1
} }
...@@ -106,9 +106,9 @@ func RemoveAll(path string) Error { ...@@ -106,9 +106,9 @@ func RemoveAll(path string) Error {
} }
// Remove directory. // Remove directory.
err1 := Remove(path); err1 := Remove(path)
if err == nil { if err == nil {
err = err1 err = err1
} }
return err; return err
} }
...@@ -5,38 +5,38 @@ ...@@ -5,38 +5,38 @@
package os_test package os_test
import ( import (
. "os"; . "os"
"testing"; "testing"
) )
func TestMkdirAll(t *testing.T) { func TestMkdirAll(t *testing.T) {
// Create new dir, in _obj so it will get // Create new dir, in _obj so it will get
// cleaned up by make if not by us. // cleaned up by make if not by us.
path := "_obj/_TestMkdirAll_/dir/./dir2"; path := "_obj/_TestMkdirAll_/dir/./dir2"
err := MkdirAll(path, 0777); err := MkdirAll(path, 0777)
if err != nil { if err != nil {
t.Fatalf("MkdirAll %q: %s", path, err) t.Fatalf("MkdirAll %q: %s", path, err)
} }
// Already exists, should succeed. // Already exists, should succeed.
err = MkdirAll(path, 0777); err = MkdirAll(path, 0777)
if err != nil { if err != nil {
t.Fatalf("MkdirAll %q (second time): %s", path, err) t.Fatalf("MkdirAll %q (second time): %s", path, err)
} }
// Make file. // Make file.
fpath := path + "/file"; fpath := path + "/file"
_, err = Open(fpath, O_WRONLY|O_CREAT, 0666); _, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
// Can't make directory named after file. // Can't make directory named after file.
err = MkdirAll(fpath, 0777); err = MkdirAll(fpath, 0777)
if err == nil { if err == nil {
t.Fatalf("MkdirAll %q: no error") t.Fatalf("MkdirAll %q: no error")
} }
perr, ok := err.(*PathError); perr, ok := err.(*PathError)
if !ok { if !ok {
t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err) t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
} }
...@@ -45,12 +45,12 @@ func TestMkdirAll(t *testing.T) { ...@@ -45,12 +45,12 @@ func TestMkdirAll(t *testing.T) {
} }
// Can't make subdirectory of file. // Can't make subdirectory of file.
ffpath := fpath + "/subdir"; ffpath := fpath + "/subdir"
err = MkdirAll(ffpath, 0777); err = MkdirAll(ffpath, 0777)
if err == nil { if err == nil {
t.Fatalf("MkdirAll %q: no error") t.Fatalf("MkdirAll %q: no error")
} }
perr, ok = err.(*PathError); perr, ok = err.(*PathError)
if !ok { if !ok {
t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err) t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
} }
...@@ -58,24 +58,24 @@ func TestMkdirAll(t *testing.T) { ...@@ -58,24 +58,24 @@ func TestMkdirAll(t *testing.T) {
t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath) t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
} }
RemoveAll("_obj/_TestMkdirAll_"); RemoveAll("_obj/_TestMkdirAll_")
} }
func TestRemoveAll(t *testing.T) { func TestRemoveAll(t *testing.T) {
// Work directory. // Work directory.
path := "_obj/_TestRemoveAll_"; path := "_obj/_TestRemoveAll_"
fpath := path + "/file"; fpath := path + "/file"
dpath := path + "/dir"; dpath := path + "/dir"
// Make directory with 1 file and remove. // Make directory with 1 file and remove.
if err := MkdirAll(path, 0777); err != nil { if err := MkdirAll(path, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", path, err) t.Fatalf("MkdirAll %q: %s", path, err)
} }
fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666); fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
fd.Close(); fd.Close()
if err = RemoveAll(path); err != nil { if err = RemoveAll(path); err != nil {
t.Fatalf("RemoveAll %q (first): %s", path, err) t.Fatalf("RemoveAll %q (first): %s", path, err)
} }
...@@ -87,16 +87,16 @@ func TestRemoveAll(t *testing.T) { ...@@ -87,16 +87,16 @@ func TestRemoveAll(t *testing.T) {
if err = MkdirAll(dpath, 0777); err != nil { if err = MkdirAll(dpath, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", dpath, err) t.Fatalf("MkdirAll %q: %s", dpath, err)
} }
fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666); fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
fd.Close(); fd.Close()
fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666); fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", fpath, err) t.Fatalf("create %q: %s", fpath, err)
} }
fd.Close(); fd.Close()
if err = RemoveAll(path); err != nil { if err = RemoveAll(path); err != nil {
t.Fatalf("RemoveAll %q (second): %s", path, err) t.Fatalf("RemoveAll %q (second): %s", path, err)
} }
...@@ -104,30 +104,30 @@ func TestRemoveAll(t *testing.T) { ...@@ -104,30 +104,30 @@ func TestRemoveAll(t *testing.T) {
t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path) t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path)
} }
if Getuid() != 0 { // Test fails as root if Getuid() != 0 { // Test fails as root
// Make directory with file and subdirectory and trigger error. // Make directory with file and subdirectory and trigger error.
if err = MkdirAll(dpath, 0777); err != nil { if err = MkdirAll(dpath, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", dpath, err) t.Fatalf("MkdirAll %q: %s", dpath, err)
} }
for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} { for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
fd, err = Open(s, O_WRONLY|O_CREAT, 0666); fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
if err != nil { if err != nil {
t.Fatalf("create %q: %s", s, err) t.Fatalf("create %q: %s", s, err)
} }
fd.Close(); fd.Close()
} }
if err = Chmod(dpath, 0); err != nil { if err = Chmod(dpath, 0); err != nil {
t.Fatalf("Chmod %q 0: %s", dpath, err) t.Fatalf("Chmod %q 0: %s", dpath, err)
} }
if err = RemoveAll(path); err == nil { if err = RemoveAll(path); err == nil {
_, err := Lstat(path); _, err := Lstat(path)
if err == nil { if err == nil {
t.Errorf("Can lstat %q after supposed RemoveAll", path) t.Errorf("Can lstat %q after supposed RemoveAll", path)
} }
t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err); t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err)
} }
perr, ok := err.(*PathError); perr, ok := err.(*PathError)
if !ok { if !ok {
t.Fatalf("RemoveAll %q returned %T not *PathError", path, err) t.Fatalf("RemoveAll %q returned %T not *PathError", path, err)
} }
......
...@@ -8,28 +8,28 @@ package os ...@@ -8,28 +8,28 @@ package os
import "syscall" import "syscall"
var Args []string // provided by runtime var Args []string // provided by runtime
var Envs []string // provided by runtime var Envs []string // provided by runtime
// Getuid returns the numeric user id of the caller. // Getuid returns the numeric user id of the caller.
func Getuid() int { return syscall.Getuid() } func Getuid() int { return syscall.Getuid() }
// Geteuid returns the numeric effective user id of the caller. // Geteuid returns the numeric effective user id of the caller.
func Geteuid() int { return syscall.Geteuid() } func Geteuid() int { return syscall.Geteuid() }
// Getgid returns the numeric group id of the caller. // Getgid returns the numeric group id of the caller.
func Getgid() int { return syscall.Getgid() } func Getgid() int { return syscall.Getgid() }
// Getegid returns the numeric effective group id of the caller. // Getegid returns the numeric effective group id of the caller.
func Getegid() int { return syscall.Getegid() } func Getegid() int { return syscall.Getegid() }
// Getgroups returns a list of the numeric ids of groups that the caller belongs to. // Getgroups returns a list of the numeric ids of groups that the caller belongs to.
func Getgroups() ([]int, Error) { func Getgroups() ([]int, Error) {
gids, errno := syscall.Getgroups(); gids, errno := syscall.Getgroups()
return gids, NewSyscallError("getgroups", errno); return gids, NewSyscallError("getgroups", errno)
} }
// Exit causes the current program to exit with the given status code. // Exit causes the current program to exit with the given status code.
// Conventionally, code zero indicates success, non-zero an error. // Conventionally, code zero indicates success, non-zero an error.
func Exit(code int) { syscall.Exit(code) } func Exit(code int) { syscall.Exit(code) }
...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool { ...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = uint64(stat.Dev); dir.Dev = uint64(stat.Dev)
dir.Ino = stat.Ino; dir.Ino = stat.Ino
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = uint32(stat.Mode); dir.Mode = uint32(stat.Mode)
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = uint64(stat.Rdev); dir.Rdev = uint64(stat.Rdev)
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec)); dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec))
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec)); dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec))
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec)); dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec))
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }
...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool { ...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = uint64(stat.Dev); dir.Dev = uint64(stat.Dev)
dir.Ino = uint64(stat.Ino); dir.Ino = uint64(stat.Ino)
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = uint32(stat.Mode); dir.Mode = uint32(stat.Mode)
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = uint64(stat.Rdev); dir.Rdev = uint64(stat.Rdev)
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec)); dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec))
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec)); dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec))
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec)); dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec))
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }
...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool { ...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = stat.Dev; dir.Dev = stat.Dev
dir.Ino = uint64(stat.Ino); dir.Ino = uint64(stat.Ino)
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = stat.Mode; dir.Mode = stat.Mode
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = stat.Rdev; dir.Rdev = stat.Rdev
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim)); dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim))
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim)); dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim))
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim)); dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim))
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }
...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool { ...@@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
} }
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
dir.Dev = uint64(stat.Dev); dir.Dev = uint64(stat.Dev)
dir.Ino = uint64(stat.Ino); dir.Ino = uint64(stat.Ino)
dir.Nlink = uint64(stat.Nlink); dir.Nlink = uint64(stat.Nlink)
dir.Mode = stat.Mode; dir.Mode = stat.Mode
dir.Uid = stat.Uid; dir.Uid = stat.Uid
dir.Gid = stat.Gid; dir.Gid = stat.Gid
dir.Rdev = uint64(stat.Rdev); dir.Rdev = uint64(stat.Rdev)
dir.Size = uint64(stat.Size); dir.Size = uint64(stat.Size)
dir.Blksize = uint64(stat.Blksize); dir.Blksize = uint64(stat.Blksize)
dir.Blocks = uint64(stat.Blocks); dir.Blocks = uint64(stat.Blocks)
dir.Atime_ns = uint64(stat.Atime) * 1e9; dir.Atime_ns = uint64(stat.Atime) * 1e9
dir.Mtime_ns = uint64(stat.Mtime) * 1e9; dir.Mtime_ns = uint64(stat.Mtime) * 1e9
dir.Ctime_ns = uint64(stat.Ctime) * 1e9; dir.Ctime_ns = uint64(stat.Ctime) * 1e9
for i := len(name) - 1; i >= 0; i-- { for i := len(name) - 1; i >= 0; i-- {
if name[i] == '/' { if name[i] == '/' {
name = name[i+1:]; name = name[i+1:]
break; break
} }
} }
dir.Name = name; dir.Name = name
if isSymlink(lstat) && !isSymlink(stat) { if isSymlink(lstat) && !isSymlink(stat) {
dir.FollowedSymlink = true dir.FollowedSymlink = true
} }
return dir; return dir
} }
...@@ -9,10 +9,10 @@ package os ...@@ -9,10 +9,10 @@ package os
import "syscall" import "syscall"
func Hostname() (name string, err Error) { func Hostname() (name string, err Error) {
var errno int; var errno int
name, errno = syscall.Sysctl("kern.hostname"); name, errno = syscall.Sysctl("kern.hostname")
if errno != 0 { if errno != 0 {
return "", NewSyscallError("sysctl kern.hostname", errno) return "", NewSyscallError("sysctl kern.hostname", errno)
} }
return name, nil; return name, nil
} }
...@@ -7,10 +7,10 @@ package os ...@@ -7,10 +7,10 @@ package os
import "syscall" import "syscall"
func Hostname() (name string, err Error) { func Hostname() (name string, err Error) {
var errno int; var errno int
name, errno = syscall.Sysctl("kern.hostname"); name, errno = syscall.Sysctl("kern.hostname")
if errno != 0 { if errno != 0 {
return "", NewSyscallError("sysctl kern.hostname", errno) return "", NewSyscallError("sysctl kern.hostname", errno)
} }
return name, nil; return name, nil
} }
...@@ -9,14 +9,14 @@ package os ...@@ -9,14 +9,14 @@ package os
// Hostname returns the host name reported by the kernel. // Hostname returns the host name reported by the kernel.
func Hostname() (name string, err Error) { func Hostname() (name string, err Error) {
f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0); f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0)
if err != nil { if err != nil {
return "", err return "", err
} }
defer f.Close(); defer f.Close()
var buf [512]byte; // Enough for a DNS name. var buf [512]byte // Enough for a DNS name.
n, err := f.Read(&buf); n, err := f.Read(&buf)
if err != nil { if err != nil {
return "", err return "", err
} }
...@@ -24,5 +24,5 @@ func Hostname() (name string, err Error) { ...@@ -24,5 +24,5 @@ func Hostname() (name string, err Error) {
if n > 0 && buf[n-1] == '\n' { if n > 0 && buf[n-1] == '\n' {
n-- n--
} }
return string(buf[0:n]), nil; return string(buf[0:n]), nil
} }
...@@ -4,4 +4,4 @@ ...@@ -4,4 +4,4 @@
package os package os
func Hostname() (name string, err Error) { return "nacl", nil } func Hostname() (name string, err Error) { return "nacl", nil }
...@@ -12,9 +12,9 @@ import "syscall" ...@@ -12,9 +12,9 @@ import "syscall"
// time is thus 1e9*sec+nsec, in nanoseconds. The zero of // time is thus 1e9*sec+nsec, in nanoseconds. The zero of
// time is the Unix epoch. // time is the Unix epoch.
func Time() (sec int64, nsec int64, err Error) { func Time() (sec int64, nsec int64, err Error) {
var tv syscall.Timeval; var tv syscall.Timeval
if errno := syscall.Gettimeofday(&tv); errno != 0 { if errno := syscall.Gettimeofday(&tv); errno != 0 {
return 0, 0, NewSyscallError("gettimeofday", errno) return 0, 0, NewSyscallError("gettimeofday", errno)
} }
return int64(tv.Sec), int64(tv.Usec) * 1000, err; return int64(tv.Sec), int64(tv.Usec) * 1000, err
} }
...@@ -10,47 +10,47 @@ import "syscall" ...@@ -10,47 +10,47 @@ import "syscall"
// OS-specific routines in this directory convert the OS-local versions to these. // OS-specific routines in this directory convert the OS-local versions to these.
// Getpagesize returns the underlying system's memory page size. // Getpagesize returns the underlying system's memory page size.
func Getpagesize() int { return syscall.Getpagesize() } func Getpagesize() int { return syscall.Getpagesize() }
// A Dir describes a file and is returned by Stat, Fstat, and Lstat // A Dir describes a file and is returned by Stat, Fstat, and Lstat
type Dir struct { type Dir struct {
Dev uint64; // device number of file system holding file. Dev uint64 // device number of file system holding file.
Ino uint64; // inode number. Ino uint64 // inode number.
Nlink uint64; // number of hard links. Nlink uint64 // number of hard links.
Mode uint32; // permission and mode bits. Mode uint32 // permission and mode bits.
Uid uint32; // user id of owner. Uid uint32 // user id of owner.
Gid uint32; // group id of owner. Gid uint32 // group id of owner.
Rdev uint64; // device type for special file. Rdev uint64 // device type for special file.
Size uint64; // length in bytes. Size uint64 // length in bytes.
Blksize uint64; // size of blocks, in bytes. Blksize uint64 // size of blocks, in bytes.
Blocks uint64; // number of blocks allocated for file. Blocks uint64 // number of blocks allocated for file.
Atime_ns uint64; // access time; nanoseconds since epoch. Atime_ns uint64 // access time; nanoseconds since epoch.
Mtime_ns uint64; // modified time; nanoseconds since epoch. Mtime_ns uint64 // modified time; nanoseconds since epoch.
Ctime_ns uint64; // status change time; nanoseconds since epoch. Ctime_ns uint64 // status change time; nanoseconds since epoch.
Name string; // name of file as presented to Open. Name string // name of file as presented to Open.
FollowedSymlink bool; // followed a symlink to get this information FollowedSymlink bool // followed a symlink to get this information
} }
// IsFifo reports whether the Dir describes a FIFO file. // IsFifo reports whether the Dir describes a FIFO file.
func (dir *Dir) IsFifo() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFIFO } func (dir *Dir) IsFifo() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFIFO }
// IsChar reports whether the Dir describes a character special file. // IsChar reports whether the Dir describes a character special file.
func (dir *Dir) IsChar() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFCHR } func (dir *Dir) IsChar() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFCHR }
// IsDirectory reports whether the Dir describes a directory. // IsDirectory reports whether the Dir describes a directory.
func (dir *Dir) IsDirectory() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFDIR } func (dir *Dir) IsDirectory() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFDIR }
// IsBlock reports whether the Dir describes a block special file. // IsBlock reports whether the Dir describes a block special file.
func (dir *Dir) IsBlock() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFBLK } func (dir *Dir) IsBlock() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFBLK }
// IsRegular reports whether the Dir describes a regular file. // IsRegular reports whether the Dir describes a regular file.
func (dir *Dir) IsRegular() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFREG } func (dir *Dir) IsRegular() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFREG }
// IsSymlink reports whether the Dir describes a symbolic link. // IsSymlink reports whether the Dir describes a symbolic link.
func (dir *Dir) IsSymlink() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFLNK } func (dir *Dir) IsSymlink() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFLNK }
// IsSocket reports whether the Dir describes a socket. // IsSocket reports whether the Dir describes a socket.
func (dir *Dir) IsSocket() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFSOCK } func (dir *Dir) IsSocket() bool { return (dir.Mode & syscall.S_IFMT) == syscall.S_IFSOCK }
// Permission returns the file permission bits. // Permission returns the file permission bits.
func (dir *Dir) Permission() int { return int(dir.Mode & 0777) } func (dir *Dir) Permission() int { return int(dir.Mode & 0777) }
...@@ -8,11 +8,11 @@ import "os" ...@@ -8,11 +8,11 @@ import "os"
// An Op is a single operation to execute to apply a patch. // An Op is a single operation to execute to apply a patch.
type Op struct { type Op struct {
Verb Verb; // action Verb Verb // action
Src string; // source file Src string // source file
Dst string; // destination file Dst string // destination file
Mode int; // mode for destination (if non-zero) Mode int // mode for destination (if non-zero)
Data []byte; // data for destination (if non-nil) Data []byte // data for destination (if non-nil)
} }
// Apply applies the patch set to the files named in the patch set, // Apply applies the patch set to the files named in the patch set,
...@@ -24,31 +24,31 @@ type Op struct { ...@@ -24,31 +24,31 @@ type Op struct {
// Typically this function will be io.ReadFile. // Typically this function will be io.ReadFile.
// //
func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) { func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) {
op := make([]Op, len(set.File)); op := make([]Op, len(set.File))
for i, f := range set.File { for i, f := range set.File {
o := &op[i]; o := &op[i]
o.Verb = f.Verb; o.Verb = f.Verb
o.Src = f.Src; o.Src = f.Src
o.Dst = f.Dst; o.Dst = f.Dst
o.Mode = f.NewMode; o.Mode = f.NewMode
if f.Diff != NoDiff || o.Verb != Edit { if f.Diff != NoDiff || o.Verb != Edit {
// Clients assume o.Data == nil means no data diff. // Clients assume o.Data == nil means no data diff.
// Start with a non-nil data. // Start with a non-nil data.
var old []byte = make([]byte, 0); // not nil var old []byte = make([]byte, 0) // not nil
var err os.Error; var err os.Error
if f.Src != "" { if f.Src != "" {
old, err = readFile(f.Src); old, err = readFile(f.Src)
if err != nil { if err != nil {
return nil, &os.PathError{string(f.Verb), f.Src, err} return nil, &os.PathError{string(f.Verb), f.Src, err}
} }
} }
o.Data, err = f.Diff.Apply(old); o.Data, err = f.Diff.Apply(old)
if err != nil { if err != nil {
return nil, &os.PathError{string(f.Verb), f.Src, err} return nil, &os.PathError{string(f.Verb), f.Src, err}
} }
} }
} }
return op, nil; return op, nil
} }
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
package patch package patch
import ( import (
"bytes"; "bytes"
"compress/zlib"; "compress/zlib"
"crypto/sha1"; "crypto/sha1"
"encoding/git85"; "encoding/git85"
"fmt"; "fmt"
"io"; "io"
"os"; "os"
) )
func gitSHA1(data []byte) []byte { func gitSHA1(data []byte) []byte {
...@@ -19,18 +19,18 @@ func gitSHA1(data []byte) []byte { ...@@ -19,18 +19,18 @@ func gitSHA1(data []byte) []byte {
// special case: 0 length is all zeros sum // special case: 0 length is all zeros sum
return make([]byte, 20) return make([]byte, 20)
} }
h := sha1.New(); h := sha1.New()
fmt.Fprintf(h, "blob %d\x00", len(data)); fmt.Fprintf(h, "blob %d\x00", len(data))
h.Write(data); h.Write(data)
return h.Sum(); return h.Sum()
} }
// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals. // BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
// GitBinaryLiteral represents a Git binary literal diff. // GitBinaryLiteral represents a Git binary literal diff.
type GitBinaryLiteral struct { type GitBinaryLiteral struct {
OldSHA1 []byte; // if non-empty, the SHA1 hash of the original OldSHA1 []byte // if non-empty, the SHA1 hash of the original
New []byte; // the new contents New []byte // the new contents
} }
// Apply implements the Diff interface's Apply method. // Apply implements the Diff interface's Apply method.
...@@ -38,7 +38,7 @@ func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, os.Error) { ...@@ -38,7 +38,7 @@ func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, os.Error) {
if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) { if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
return nil, ErrPatchFailure return nil, ErrPatchFailure
} }
return d.New, nil; return d.New, nil
} }
func unhex(c byte) uint8 { func unhex(c byte) uint8 {
...@@ -50,60 +50,60 @@ func unhex(c byte) uint8 { ...@@ -50,60 +50,60 @@ func unhex(c byte) uint8 {
case 'A' <= c && c <= 'F': case 'A' <= c && c <= 'F':
return c - 'A' + 10 return c - 'A' + 10
} }
return 255; return 255
} }
func getHex(s []byte) (data []byte, rest []byte) { func getHex(s []byte) (data []byte, rest []byte) {
n := 0; n := 0
for n < len(s) && unhex(s[n]) != 255 { for n < len(s) && unhex(s[n]) != 255 {
n++ n++
} }
n &^= 1; // Only take an even number of hex digits. n &^= 1 // Only take an even number of hex digits.
data = make([]byte, n/2); data = make([]byte, n/2)
for i := range data { for i := range data {
data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1]) data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
} }
rest = s[n:]; rest = s[n:]
return; return
} }
// ParseGitBinary parses raw as a Git binary patch. // ParseGitBinary parses raw as a Git binary patch.
func ParseGitBinary(raw []byte) (Diff, os.Error) { func ParseGitBinary(raw []byte) (Diff, os.Error) {
var oldSHA1, newSHA1 []byte; var oldSHA1, newSHA1 []byte
var sawBinary bool; var sawBinary bool
for { for {
var first []byte; var first []byte
first, raw, _ = getLine(raw, 1); first, raw, _ = getLine(raw, 1)
first = bytes.TrimSpace(first); first = bytes.TrimSpace(first)
if s, ok := skip(first, "index "); ok { if s, ok := skip(first, "index "); ok {
oldSHA1, s = getHex(s); oldSHA1, s = getHex(s)
if s, ok = skip(s, ".."); !ok { if s, ok = skip(s, ".."); !ok {
continue continue
} }
newSHA1, s = getHex(s); newSHA1, s = getHex(s)
continue; continue
} }
if _, ok := skip(first, "GIT binary patch"); ok { if _, ok := skip(first, "GIT binary patch"); ok {
sawBinary = true; sawBinary = true
continue; continue
} }
if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary { if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
data := make([]byte, n); data := make([]byte, n)
d := git85.NewDecoder(bytes.NewBuffer(raw)); d := git85.NewDecoder(bytes.NewBuffer(raw))
z, err := zlib.NewInflater(d); z, err := zlib.NewInflater(d)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer z.Close(); defer z.Close()
if _, err = io.ReadFull(z, data); err != nil { if _, err = io.ReadFull(z, data); err != nil {
if err == os.EOF { if err == os.EOF {
err = io.ErrUnexpectedEOF err = io.ErrUnexpectedEOF
} }
return nil, err; return nil, err
} }
var buf [1]byte; var buf [1]byte
m, err := z.Read(&buf); m, err := z.Read(&buf)
if m != 0 || err != os.EOF { if m != 0 || err != os.EOF {
return nil, os.NewError("Git binary literal longer than expected") return nil, os.NewError("Git binary literal longer than expected")
} }
...@@ -111,11 +111,11 @@ func ParseGitBinary(raw []byte) (Diff, os.Error) { ...@@ -111,11 +111,11 @@ func ParseGitBinary(raw []byte) (Diff, os.Error) {
if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) { if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
return nil, os.NewError("Git binary literal SHA1 mismatch") return nil, os.NewError("Git binary literal SHA1 mismatch")
} }
return &GitBinaryLiteral{oldSHA1, data}, nil; return &GitBinaryLiteral{oldSHA1, data}, nil
} }
if !sawBinary { if !sawBinary {
return nil, os.NewError("unexpected Git patch header: " + string(first)) return nil, os.NewError("unexpected Git patch header: " + string(first))
} }
} }
panic("unreachable"); panic("unreachable")
} }
...@@ -8,37 +8,37 @@ ...@@ -8,37 +8,37 @@
package patch package patch
import ( import (
"bytes"; "bytes"
"os"; "os"
"path"; "path"
"strings"; "strings"
) )
// A Set represents a set of patches to be applied as a single atomic unit. // A Set represents a set of patches to be applied as a single atomic unit.
// Patch sets are often preceded by a descriptive header. // Patch sets are often preceded by a descriptive header.
type Set struct { type Set struct {
Header string; // free-form text Header string // free-form text
File []*File; File []*File
} }
// A File represents a collection of changes to be made to a single file. // A File represents a collection of changes to be made to a single file.
type File struct { type File struct {
Verb Verb; Verb Verb
Src string; // source for Verb == Copy, Verb == Rename Src string // source for Verb == Copy, Verb == Rename
Dst string; Dst string
OldMode, NewMode int; // 0 indicates not used OldMode, NewMode int // 0 indicates not used
Diff; // changes to data; == NoDiff if operation does not edit file Diff // changes to data; == NoDiff if operation does not edit file
} }
// A Verb is an action performed on a file. // A Verb is an action performed on a file.
type Verb string type Verb string
const ( const (
Add Verb = "add"; Add Verb = "add"
Copy Verb = "copy"; Copy Verb = "copy"
Delete Verb = "delete"; Delete Verb = "delete"
Edit Verb = "edit"; Edit Verb = "edit"
Rename Verb = "rename"; Rename Verb = "rename"
) )
// A Diff is any object that describes changes to transform // A Diff is any object that describes changes to transform
...@@ -47,7 +47,7 @@ type Diff interface { ...@@ -47,7 +47,7 @@ type Diff interface {
// Apply applies the changes listed in the diff // Apply applies the changes listed in the diff
// to the string s, returning the new version of the string. // to the string s, returning the new version of the string.
// Note that the string s need not be a text string. // Note that the string s need not be a text string.
Apply(old []byte) (new []byte, err os.Error); Apply(old []byte) (new []byte, err os.Error)
} }
// NoDiff is a no-op Diff implementation: it passes the // NoDiff is a no-op Diff implementation: it passes the
...@@ -63,7 +63,7 @@ func (noDiffType) Apply(old []byte) ([]byte, os.Error) { ...@@ -63,7 +63,7 @@ func (noDiffType) Apply(old []byte) ([]byte, os.Error) {
// A SyntaxError represents a syntax error encountered while parsing a patch. // A SyntaxError represents a syntax error encountered while parsing a patch.
type SyntaxError string type SyntaxError string
func (e SyntaxError) String() string { return string(e) } func (e SyntaxError) String() string { return string(e) }
var newline = []byte{'\n'} var newline = []byte{'\n'}
...@@ -82,37 +82,37 @@ func Parse(text []byte) (*Set, os.Error) { ...@@ -82,37 +82,37 @@ func Parse(text []byte) (*Set, os.Error) {
// diff [--git] a/file/path b/file/path. // diff [--git] a/file/path b/file/path.
// //
// First look for Index: lines. If none, fall back on diff lines. // First look for Index: lines. If none, fall back on diff lines.
text, files := sections(text, "Index: "); text, files := sections(text, "Index: ")
if len(files) == 0 { if len(files) == 0 {
text, files = sections(text, "diff ") text, files = sections(text, "diff ")
} }
set := &Set{string(text), make([]*File, len(files))}; set := &Set{string(text), make([]*File, len(files))}
// Parse file header and then // Parse file header and then
// parse files into patch chunks. // parse files into patch chunks.
// Each chunk begins with @@. // Each chunk begins with @@.
for i, raw := range files { for i, raw := range files {
p := new(File); p := new(File)
set.File[i] = p; set.File[i] = p
// First line of hdr is the Index: that // First line of hdr is the Index: that
// begins the section. After that is the file name. // begins the section. After that is the file name.
s, raw, _ := getLine(raw, 1); s, raw, _ := getLine(raw, 1)
if hasPrefix(s, "Index: ") { if hasPrefix(s, "Index: ") {
p.Dst = string(bytes.TrimSpace(s[7:])); p.Dst = string(bytes.TrimSpace(s[7:]))
goto HaveName; goto HaveName
} else if hasPrefix(s, "diff ") { } else if hasPrefix(s, "diff ") {
str := string(bytes.TrimSpace(s)); str := string(bytes.TrimSpace(s))
i := strings.LastIndex(str, " b/"); i := strings.LastIndex(str, " b/")
if i >= 0 { if i >= 0 {
p.Dst = str[i+3:]; p.Dst = str[i+3:]
goto HaveName; goto HaveName
} }
} }
return nil, SyntaxError("unexpected patch header line: " + string(s)); return nil, SyntaxError("unexpected patch header line: " + string(s))
HaveName: HaveName:
p.Dst = path.Clean(p.Dst); p.Dst = path.Clean(p.Dst)
if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") { if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
return nil, SyntaxError("invalid path: " + p.Dst) return nil, SyntaxError("invalid path: " + p.Dst)
} }
...@@ -126,55 +126,55 @@ func Parse(text []byte) (*Set, os.Error) { ...@@ -126,55 +126,55 @@ func Parse(text []byte) (*Set, os.Error) {
// rename to %s // rename to %s
// copy from %s - file copied from other file // copy from %s - file copied from other file
// copy to %s // copy to %s
p.Verb = Edit; p.Verb = Edit
for len(raw) > 0 { for len(raw) > 0 {
oldraw := raw; oldraw := raw
var l []byte; var l []byte
l, raw, _ = getLine(raw, 1); l, raw, _ = getLine(raw, 1)
l = bytes.TrimSpace(l); l = bytes.TrimSpace(l)
if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
p.NewMode = m; p.NewMode = m
p.Verb = Add; p.Verb = Add
continue; continue
} }
if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
p.OldMode = m; p.OldMode = m
p.Verb = Delete; p.Verb = Delete
p.Src = p.Dst; p.Src = p.Dst
p.Dst = ""; p.Dst = ""
continue; continue
} }
if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
// usually implies p.Verb = "rename" or "copy" // usually implies p.Verb = "rename" or "copy"
// but we'll get that from the rename or copy line. // but we'll get that from the rename or copy line.
p.OldMode = m; p.OldMode = m
continue; continue
} }
if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
p.OldMode = m; p.OldMode = m
continue; continue
} }
if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 { if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
p.NewMode = m; p.NewMode = m
continue; continue
} }
if s, ok := skip(l, "rename from "); ok && len(s) > 0 { if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
p.Src = string(s); p.Src = string(s)
p.Verb = Rename; p.Verb = Rename
continue; continue
} }
if s, ok := skip(l, "rename to "); ok && len(s) > 0 { if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
p.Verb = Rename; p.Verb = Rename
continue; continue
} }
if s, ok := skip(l, "copy from "); ok && len(s) > 0 { if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
p.Src = string(s); p.Src = string(s)
p.Verb = Copy; p.Verb = Copy
continue; continue
} }
if s, ok := skip(l, "copy to "); ok && len(s) > 0 { if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
p.Verb = Copy; p.Verb = Copy
continue; continue
} }
if s, ok := skip(l, "Binary file "); ok && len(s) > 0 { if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
// Hg prints // Hg prints
...@@ -200,22 +200,22 @@ func Parse(text []byte) (*Set, os.Error) { ...@@ -200,22 +200,22 @@ func Parse(text []byte) (*Set, os.Error) {
continue continue
} }
if hasPrefix(l, "@@ -") { if hasPrefix(l, "@@ -") {
diff, err := ParseTextDiff(oldraw); diff, err := ParseTextDiff(oldraw)
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.Diff = diff; p.Diff = diff
break; break
} }
if hasPrefix(l, "index ") || hasPrefix(l, "GIT binary patch") { if hasPrefix(l, "index ") || hasPrefix(l, "GIT binary patch") {
diff, err := ParseGitBinary(oldraw); diff, err := ParseGitBinary(oldraw)
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.Diff = diff; p.Diff = diff
break; break
} }
return nil, SyntaxError("unexpected patch header line: " + string(l)); return nil, SyntaxError("unexpected patch header line: " + string(l))
} }
if p.Diff == nil { if p.Diff == nil {
p.Diff = NoDiff p.Diff = NoDiff
...@@ -225,25 +225,25 @@ func Parse(text []byte) (*Set, os.Error) { ...@@ -225,25 +225,25 @@ func Parse(text []byte) (*Set, os.Error) {
} }
} }
return set, nil; return set, nil
} }
// getLine returns the first n lines of data and the remainder. // getLine returns the first n lines of data and the remainder.
// If data has no newline, getLine returns data, nil, false // If data has no newline, getLine returns data, nil, false
func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) { func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
rest = data; rest = data
ok = true; ok = true
for ; n > 0; n-- { for ; n > 0; n-- {
nl := bytes.Index(rest, newline); nl := bytes.Index(rest, newline)
if nl < 0 { if nl < 0 {
rest = nil; rest = nil
ok = false; ok = false
break; break
} }
rest = rest[nl+1:]; rest = rest[nl+1:]
} }
first = data[0 : len(data)-len(rest)]; first = data[0 : len(data)-len(rest)]
return; return
} }
// sections returns a collection of file sections, // sections returns a collection of file sections,
...@@ -251,34 +251,34 @@ func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) { ...@@ -251,34 +251,34 @@ func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
// text before the first instance of such a line is // text before the first instance of such a line is
// returned separately. // returned separately.
func sections(text []byte, prefix string) ([]byte, [][]byte) { func sections(text []byte, prefix string) ([]byte, [][]byte) {
n := 0; n := 0
for b := text; ; { for b := text; ; {
if hasPrefix(b, prefix) { if hasPrefix(b, prefix) {
n++ n++
} }
nl := bytes.Index(b, newline); nl := bytes.Index(b, newline)
if nl < 0 { if nl < 0 {
break break
} }
b = b[nl+1:]; b = b[nl+1:]
} }
sect := make([][]byte, n+1); sect := make([][]byte, n+1)
n = 0; n = 0
for b := text; ; { for b := text; ; {
if hasPrefix(b, prefix) { if hasPrefix(b, prefix) {
sect[n] = text[0 : len(text)-len(b)]; sect[n] = text[0 : len(text)-len(b)]
n++; n++
text = b; text = b
} }
nl := bytes.Index(b, newline); nl := bytes.Index(b, newline)
if nl < 0 { if nl < 0 {
sect[n] = text; sect[n] = text
break; break
} }
b = b[nl+1:]; b = b[nl+1:]
} }
return sect[0], sect[1:]; return sect[0], sect[1:]
} }
// if s begins with the prefix t, skip returns // if s begins with the prefix t, skip returns
...@@ -287,7 +287,7 @@ func skip(s []byte, t string) (ss []byte, ok bool) { ...@@ -287,7 +287,7 @@ func skip(s []byte, t string) (ss []byte, ok bool) {
if len(s) < len(t) || string(s[0:len(t)]) != t { if len(s) < len(t) || string(s[0:len(t)]) != t {
return nil, false return nil, false
} }
return s[len(t):], true; return s[len(t):], true
} }
// if s begins with the prefix t and then is a sequence // if s begins with the prefix t and then is a sequence
...@@ -298,22 +298,22 @@ func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) { ...@@ -298,22 +298,22 @@ func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) {
if s, ok = skip(s, t); !ok { if s, ok = skip(s, t); !ok {
return return
} }
var i int; var i int
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ { for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
n = n*base + int(s[i]-'0') n = n*base + int(s[i]-'0')
} }
if i == 0 { if i == 0 {
return return
} }
return n, s[i:], true; return n, s[i:], true
} }
// hasPrefix returns true if s begins with t. // hasPrefix returns true if s begins with t.
func hasPrefix(s []byte, t string) bool { func hasPrefix(s []byte, t string) bool {
_, ok := skip(s, t); _, ok := skip(s, t)
return ok; return ok
} }
// splitLines returns the result of splitting s into lines. // splitLines returns the result of splitting s into lines.
// The \n on each line is preserved. // The \n on each line is preserved.
func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline, 0) } func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline, 0) }
...@@ -7,31 +7,31 @@ package patch ...@@ -7,31 +7,31 @@ package patch
// TODO(rsc): test Apply // TODO(rsc): test Apply
import ( import (
"strings"; "strings"
"testing"; "testing"
) )
type Test struct { type Test struct {
in string; in string
out string; out string
diff string; diff string
} }
func TestFileApply(t *testing.T) { func TestFileApply(t *testing.T) {
for i, test := range tests { for i, test := range tests {
set, err := Parse(strings.Bytes(test.diff)); set, err := Parse(strings.Bytes(test.diff))
if err != nil { if err != nil {
t.Errorf("#%d: Parse: %s", i, err); t.Errorf("#%d: Parse: %s", i, err)
continue; continue
} }
if len(set.File) != 1 { if len(set.File) != 1 {
t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File)); t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File))
continue; continue
} }
new, err := set.File[0].Apply(strings.Bytes(test.in)); new, err := set.File[0].Apply(strings.Bytes(test.in))
if err != nil { if err != nil {
t.Errorf("#%d: Apply: %s", i, err); t.Errorf("#%d: Apply: %s", i, err)
continue; continue
} }
if s := string(new); s != test.out { if s := string(new); s != test.out {
t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out) t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out)
......
package patch package patch
import ( import (
"bytes"; "bytes"
"os"; "os"
) )
type TextDiff []TextChunk type TextDiff []TextChunk
...@@ -11,25 +11,25 @@ type TextDiff []TextChunk ...@@ -11,25 +11,25 @@ type TextDiff []TextChunk
// the text beginning at Line, which should be exactly Old, // the text beginning at Line, which should be exactly Old,
// is to be replaced with New. // is to be replaced with New.
type TextChunk struct { type TextChunk struct {
Line int; Line int
Old []byte; Old []byte
New []byte; New []byte
} }
func ParseTextDiff(raw []byte) (TextDiff, os.Error) { func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
// Copy raw so it is safe to keep references to slices. // Copy raw so it is safe to keep references to slices.
_, chunks := sections(raw, "@@ -"); _, chunks := sections(raw, "@@ -")
delta := 0; delta := 0
diff := make(TextDiff, len(chunks)); diff := make(TextDiff, len(chunks))
for i, raw := range chunks { for i, raw := range chunks {
c := &diff[i]; c := &diff[i]
// Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk // Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
chunk := splitLines(raw); chunk := splitLines(raw)
chunkHeader := chunk[0]; chunkHeader := chunk[0]
var ok bool; var ok bool
var oldLine, oldCount, newLine, newCount int; var oldLine, oldCount, newLine, newCount int
s := chunkHeader; s := chunkHeader
if oldLine, s, ok = atoi(s, "@@ -", 10); !ok { if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
ErrChunkHdr: ErrChunkHdr:
return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader)) return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
...@@ -61,16 +61,16 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { ...@@ -61,16 +61,16 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
} }
// Count lines in text // Count lines in text
var dropOldNL, dropNewNL bool; var dropOldNL, dropNewNL bool
var nold, nnew int; var nold, nnew int
var lastch byte; var lastch byte
chunk = chunk[1:]; chunk = chunk[1:]
for _, l := range chunk { for _, l := range chunk {
if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') { if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
if len(bytes.TrimSpace(l)) != 0 { if len(bytes.TrimSpace(l)) != 0 {
return nil, SyntaxError("too many chunk lines") return nil, SyntaxError("too many chunk lines")
} }
continue; continue
} }
if len(l) == 0 { if len(l) == 0 {
return nil, SyntaxError("empty chunk line") return nil, SyntaxError("empty chunk line")
...@@ -81,8 +81,8 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { ...@@ -81,8 +81,8 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
case '-': case '-':
nold++ nold++
case ' ': case ' ':
nnew++; nnew++
nold++; nold++
case '\\': case '\\':
if _, ok := skip(l, "\\ No newline at end of file"); ok { if _, ok := skip(l, "\\ No newline at end of file"); ok {
switch lastch { switch lastch {
...@@ -91,18 +91,18 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { ...@@ -91,18 +91,18 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
case '+': case '+':
dropNewNL = true dropNewNL = true
case ' ': case ' ':
dropOldNL = true; dropOldNL = true
dropNewNL = true; dropNewNL = true
default: default:
return nil, SyntaxError("message `\\ No newline at end of file' out of context") return nil, SyntaxError("message `\\ No newline at end of file' out of context")
} }
break; break
} }
fallthrough; fallthrough
default: default:
return nil, SyntaxError("unexpected chunk line: " + string(l)) return nil, SyntaxError("unexpected chunk line: " + string(l))
} }
lastch = l[0]; lastch = l[0]
} }
// Does it match the header? // Does it match the header?
...@@ -112,31 +112,31 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { ...@@ -112,31 +112,31 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
if oldLine+delta != newLine { if oldLine+delta != newLine {
return nil, SyntaxError("chunk delta is out of sync with previous chunks") return nil, SyntaxError("chunk delta is out of sync with previous chunks")
} }
delta += nnew - nold; delta += nnew - nold
c.Line = oldLine; c.Line = oldLine
var old, new bytes.Buffer; var old, new bytes.Buffer
nold = 0; nold = 0
nnew = 0; nnew = 0
for _, l := range chunk { for _, l := range chunk {
if nold == oldCount && nnew == newCount { if nold == oldCount && nnew == newCount {
break break
} }
ch, l := l[0], l[1:]; ch, l := l[0], l[1:]
if ch == '\\' { if ch == '\\' {
continue continue
} }
if ch != '+' { if ch != '+' {
old.Write(l); old.Write(l)
nold++; nold++
} }
if ch != '-' { if ch != '-' {
new.Write(l); new.Write(l)
nnew++; nnew++
} }
} }
c.Old = old.Bytes(); c.Old = old.Bytes()
c.New = new.Bytes(); c.New = new.Bytes()
if dropOldNL { if dropOldNL {
c.Old = c.Old[0 : len(c.Old)-1] c.Old = c.Old[0 : len(c.Old)-1]
} }
...@@ -144,7 +144,7 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { ...@@ -144,7 +144,7 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
c.New = c.New[0 : len(c.New)-1] c.New = c.New[0 : len(c.New)-1]
} }
} }
return diff, nil; return diff, nil
} }
var ErrPatchFailure = os.NewError("patch did not apply cleanly") var ErrPatchFailure = os.NewError("patch did not apply cleanly")
...@@ -152,20 +152,20 @@ var ErrPatchFailure = os.NewError("patch did not apply cleanly") ...@@ -152,20 +152,20 @@ var ErrPatchFailure = os.NewError("patch did not apply cleanly")
// Apply applies the changes listed in the diff // Apply applies the changes listed in the diff
// to the data, returning the new version. // to the data, returning the new version.
func (d TextDiff) Apply(data []byte) ([]byte, os.Error) { func (d TextDiff) Apply(data []byte) ([]byte, os.Error) {
var buf bytes.Buffer; var buf bytes.Buffer
line := 1; line := 1
for _, c := range d { for _, c := range d {
var ok bool; var ok bool
var prefix []byte; var prefix []byte
prefix, data, ok = getLine(data, c.Line-line); prefix, data, ok = getLine(data, c.Line-line)
if !ok || !bytes.HasPrefix(data, c.Old) { if !ok || !bytes.HasPrefix(data, c.Old) {
return nil, ErrPatchFailure return nil, ErrPatchFailure
} }
buf.Write(prefix); buf.Write(prefix)
data = data[len(c.Old):]; data = data[len(c.Old):]
buf.Write(c.New); buf.Write(c.New)
line = c.Line + bytes.Count(c.Old, newline); line = c.Line + bytes.Count(c.Old, newline)
} }
buf.Write(data); buf.Write(data)
return buf.Bytes(), nil; return buf.Bytes(), nil
} }
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
package path package path
import ( import (
"io/ioutil"; "io/ioutil"
"os"; "os"
"strings"; "strings"
) )
// Clean returns the shortest path name equivalent to path // Clean returns the shortest path name equivalent to path
...@@ -34,16 +34,16 @@ func Clean(path string) string { ...@@ -34,16 +34,16 @@ func Clean(path string) string {
return "." return "."
} }
rooted := path[0] == '/'; rooted := path[0] == '/'
n := len(path); n := len(path)
// Invariants: // Invariants:
// reading from path; r is index of next byte to process. // reading from path; r is index of next byte to process.
// writing to buf; w is index of next byte to write. // writing to buf; w is index of next byte to write.
// dotdot is index in buf where .. must stop, either because // dotdot is index in buf where .. must stop, either because
// it is the leading slash or it is a leading ../../.. prefix. // it is the leading slash or it is a leading ../../.. prefix.
buf := strings.Bytes(path); buf := strings.Bytes(path)
r, w, dotdot := 0, 0, 0; r, w, dotdot := 0, 0, 0
if rooted { if rooted {
r, w, dotdot = 1, 1, 1 r, w, dotdot = 1, 1, 1
} }
...@@ -58,48 +58,48 @@ func Clean(path string) string { ...@@ -58,48 +58,48 @@ func Clean(path string) string {
r++ r++
case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'): case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
// .. element: remove to last / // .. element: remove to last /
r += 2; r += 2
switch { switch {
case w > dotdot: case w > dotdot:
// can backtrack // can backtrack
w--; w--
for w > dotdot && buf[w] != '/' { for w > dotdot && buf[w] != '/' {
w-- w--
} }
case !rooted: case !rooted:
// cannot backtrack, but not rooted, so append .. element. // cannot backtrack, but not rooted, so append .. element.
if w > 0 { if w > 0 {
buf[w] = '/'; buf[w] = '/'
w++; w++
} }
buf[w] = '.'; buf[w] = '.'
w++; w++
buf[w] = '.'; buf[w] = '.'
w++; w++
dotdot = w; dotdot = w
} }
default: default:
// real path element. // real path element.
// add slash if needed // add slash if needed
if rooted && w != 1 || !rooted && w != 0 { if rooted && w != 1 || !rooted && w != 0 {
buf[w] = '/'; buf[w] = '/'
w++; w++
} }
// copy element // copy element
for ; r < n && path[r] != '/'; r++ { for ; r < n && path[r] != '/'; r++ {
buf[w] = path[r]; buf[w] = path[r]
w++; w++
} }
} }
} }
// Turn empty string into "." // Turn empty string into "."
if w == 0 { if w == 0 {
buf[w] = '.'; buf[w] = '.'
w++; w++
} }
return string(buf[0:w]); return string(buf[0:w])
} }
// Split splits path immediately following the final slash, // Split splits path immediately following the final slash,
...@@ -112,7 +112,7 @@ func Split(path string) (dir, file string) { ...@@ -112,7 +112,7 @@ func Split(path string) (dir, file string) {
return path[0 : i+1], path[i+1:] return path[0 : i+1], path[i+1:]
} }
} }
return "", path; return "", path
} }
// Join joins dir and file into a single path, adding a separating // Join joins dir and file into a single path, adding a separating
...@@ -121,7 +121,7 @@ func Join(dir, file string) string { ...@@ -121,7 +121,7 @@ func Join(dir, file string) string {
if dir == "" { if dir == "" {
return file return file
} }
return Clean(dir + "/" + file); return Clean(dir + "/" + file)
} }
// Ext returns the file name extension used by path. // Ext returns the file name extension used by path.
...@@ -134,28 +134,28 @@ func Ext(path string) string { ...@@ -134,28 +134,28 @@ func Ext(path string) string {
return path[i:] return path[i:]
} }
} }
return ""; return ""
} }
// Visitor methods are invoked for corresponding file tree entries // Visitor methods are invoked for corresponding file tree entries
// visited by Walk. The parameter path is the full path of d relative // visited by Walk. The parameter path is the full path of d relative
// to root. // to root.
type Visitor interface { type Visitor interface {
VisitDir(path string, d *os.Dir) bool; VisitDir(path string, d *os.Dir) bool
VisitFile(path string, d *os.Dir); VisitFile(path string, d *os.Dir)
} }
func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) { func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
if !d.IsDirectory() { if !d.IsDirectory() {
v.VisitFile(path, d); v.VisitFile(path, d)
return; return
} }
if !v.VisitDir(path, d) { if !v.VisitDir(path, d) {
return // skip directory entries return // skip directory entries
} }
list, err := ioutil.ReadDir(path); list, err := ioutil.ReadDir(path)
if err != nil { if err != nil {
if errors != nil { if errors != nil {
errors <- err errors <- err
...@@ -175,12 +175,12 @@ func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) { ...@@ -175,12 +175,12 @@ func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
// If errors != nil, Walk sends each directory read error // If errors != nil, Walk sends each directory read error
// to the channel. Otherwise Walk discards the error. // to the channel. Otherwise Walk discards the error.
func Walk(root string, v Visitor, errors chan<- os.Error) { func Walk(root string, v Visitor, errors chan<- os.Error) {
d, err := os.Lstat(root); d, err := os.Lstat(root)
if err != nil { if err != nil {
if errors != nil { if errors != nil {
errors <- err errors <- err
} }
return; // can't progress return // can't progress
} }
walk(root, d, v, errors); walk(root, d, v, errors)
} }
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
package path package path
import ( import (
"os"; "os"
"testing"; "testing"
) )
type CleanTest struct { type CleanTest struct {
path, clean string; path, clean string
} }
var cleantests = []CleanTest{ var cleantests = []CleanTest{
...@@ -72,7 +72,7 @@ func TestClean(t *testing.T) { ...@@ -72,7 +72,7 @@ func TestClean(t *testing.T) {
} }
type SplitTest struct { type SplitTest struct {
path, dir, file string; path, dir, file string
} }
var splittests = []SplitTest{ var splittests = []SplitTest{
...@@ -92,7 +92,7 @@ func TestSplit(t *testing.T) { ...@@ -92,7 +92,7 @@ func TestSplit(t *testing.T) {
} }
type JoinTest struct { type JoinTest struct {
dir, file, path string; dir, file, path string
} }
var jointests = []JoinTest{ var jointests = []JoinTest{
...@@ -114,7 +114,7 @@ func TestJoin(t *testing.T) { ...@@ -114,7 +114,7 @@ func TestJoin(t *testing.T) {
} }
type ExtTest struct { type ExtTest struct {
path, ext string; path, ext string
} }
var exttests = []ExtTest{ var exttests = []ExtTest{
...@@ -134,9 +134,9 @@ func TestExt(t *testing.T) { ...@@ -134,9 +134,9 @@ func TestExt(t *testing.T) {
} }
type Node struct { type Node struct {
name string; name string
entries []*Node; // nil if the entry is a file entries []*Node // nil if the entry is a file
mark int; mark int
} }
var tree = &Node{ var tree = &Node{
...@@ -166,7 +166,7 @@ var tree = &Node{ ...@@ -166,7 +166,7 @@ var tree = &Node{
} }
func walkTree(n *Node, path string, f func(path string, n *Node)) { func walkTree(n *Node, path string, f func(path string, n *Node)) {
f(path, n); f(path, n)
for _, e := range n.entries { for _, e := range n.entries {
walkTree(e, Join(path, e.name), f) walkTree(e, Join(path, e.name), f)
} }
...@@ -175,25 +175,25 @@ func walkTree(n *Node, path string, f func(path string, n *Node)) { ...@@ -175,25 +175,25 @@ func walkTree(n *Node, path string, f func(path string, n *Node)) {
func makeTree(t *testing.T) { func makeTree(t *testing.T) {
walkTree(tree, tree.name, func(path string, n *Node) { walkTree(tree, tree.name, func(path string, n *Node) {
if n.entries == nil { if n.entries == nil {
fd, err := os.Open(path, os.O_CREAT, 0660); fd, err := os.Open(path, os.O_CREAT, 0660)
if err != nil { if err != nil {
t.Errorf("makeTree: %v", err) t.Errorf("makeTree: %v", err)
} }
fd.Close(); fd.Close()
} else { } else {
os.Mkdir(path, 0770) os.Mkdir(path, 0770)
} }
}) })
} }
func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) } func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) }
func checkMarks(t *testing.T) { func checkMarks(t *testing.T) {
walkTree(tree, tree.name, func(path string, n *Node) { walkTree(tree, tree.name, func(path string, n *Node) {
if n.mark != 1 { if n.mark != 1 {
t.Errorf("node %s mark = %d; expected 1", path, n.mark) t.Errorf("node %s mark = %d; expected 1", path, n.mark)
} }
n.mark = 0; n.mark = 0
}) })
} }
...@@ -209,8 +209,8 @@ func mark(name string) { ...@@ -209,8 +209,8 @@ func mark(name string) {
type TestVisitor struct{} type TestVisitor struct{}
func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool { func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool {
mark(d.Name); mark(d.Name)
return true; return true
} }
func (v *TestVisitor) VisitFile(path string, d *os.Dir) { func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
...@@ -218,52 +218,52 @@ func (v *TestVisitor) VisitFile(path string, d *os.Dir) { ...@@ -218,52 +218,52 @@ func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
} }
func TestWalk(t *testing.T) { func TestWalk(t *testing.T) {
makeTree(t); makeTree(t)
// 1) ignore error handling, expect none // 1) ignore error handling, expect none
v := &TestVisitor{}; v := &TestVisitor{}
Walk(tree.name, v, nil); Walk(tree.name, v, nil)
checkMarks(t); checkMarks(t)
// 2) handle errors, expect none // 2) handle errors, expect none
errors := make(chan os.Error, 64); errors := make(chan os.Error, 64)
Walk(tree.name, v, errors); Walk(tree.name, v, errors)
if err, ok := <-errors; ok { if err, ok := <-errors; ok {
t.Errorf("no error expected, found: s", err) t.Errorf("no error expected, found: s", err)
} }
checkMarks(t); checkMarks(t)
if os.Getuid() != 0 { if os.Getuid() != 0 {
// introduce 2 errors: chmod top-level directories to 0 // introduce 2 errors: chmod top-level directories to 0
os.Chmod(Join(tree.name, tree.entries[1].name), 0); os.Chmod(Join(tree.name, tree.entries[1].name), 0)
os.Chmod(Join(tree.name, tree.entries[3].name), 0); os.Chmod(Join(tree.name, tree.entries[3].name), 0)
// mark respective subtrees manually // mark respective subtrees manually
markTree(tree.entries[1]); markTree(tree.entries[1])
markTree(tree.entries[3]); markTree(tree.entries[3])
// correct double-marking of directory itself // correct double-marking of directory itself
tree.entries[1].mark--; tree.entries[1].mark--
tree.entries[3].mark--; tree.entries[3].mark--
// 3) handle errors, expect two // 3) handle errors, expect two
errors = make(chan os.Error, 64); errors = make(chan os.Error, 64)
os.Chmod(Join(tree.name, tree.entries[1].name), 0); os.Chmod(Join(tree.name, tree.entries[1].name), 0)
Walk(tree.name, v, errors); Walk(tree.name, v, errors)
for i := 1; i <= 2; i++ { for i := 1; i <= 2; i++ {
if _, ok := <-errors; !ok { if _, ok := <-errors; !ok {
t.Errorf("%d. error expected, none found", i); t.Errorf("%d. error expected, none found", i)
break; break
} }
} }
if err, ok := <-errors; ok { if err, ok := <-errors; ok {
t.Errorf("only two errors expected, found 3rd: %v", err) t.Errorf("only two errors expected, found 3rd: %v", err)
} }
// the inaccessible subtrees were marked manually // the inaccessible subtrees were marked manually
checkMarks(t); checkMarks(t)
} }
// cleanup // cleanup
os.Chmod(Join(tree.name, tree.entries[1].name), 0770); os.Chmod(Join(tree.name, tree.entries[1].name), 0770)
os.Chmod(Join(tree.name, tree.entries[3].name), 0770); os.Chmod(Join(tree.name, tree.entries[3].name), 0770)
if err := os.RemoveAll(tree.name); err != nil { if err := os.RemoveAll(tree.name); err != nil {
t.Errorf("removeTree: %v", err) t.Errorf("removeTree: %v", err)
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package rand package rand
import ( import (
"math"; "math"
) )
/* /*
...@@ -17,7 +17,7 @@ import ( ...@@ -17,7 +17,7 @@ import (
*/ */
const ( const (
re = 7.69711747013104972; re = 7.69711747013104972
) )
// ExpFloat64 returns an exponentially distributed float64 in the range // ExpFloat64 returns an exponentially distributed float64 in the range
...@@ -30,9 +30,9 @@ const ( ...@@ -30,9 +30,9 @@ const (
// //
func (r *Rand) ExpFloat64() float64 { func (r *Rand) ExpFloat64() float64 {
for { for {
j := r.Uint32(); j := r.Uint32()
i := j & 0xFF; i := j & 0xFF
x := float64(j) * float64(we[i]); x := float64(j) * float64(we[i])
if j < ke[i] { if j < ke[i] {
return x return x
} }
...@@ -43,7 +43,7 @@ func (r *Rand) ExpFloat64() float64 { ...@@ -43,7 +43,7 @@ func (r *Rand) ExpFloat64() float64 {
return x return x
} }
} }
panic("unreachable"); panic("unreachable")
} }
var ke = [256]uint32{ var ke = [256]uint32{
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package rand package rand
import ( import (
"math"; "math"
) )
/* /*
...@@ -17,14 +17,14 @@ import ( ...@@ -17,14 +17,14 @@ import (
*/ */
const ( const (
rn = 3.442619855899; rn = 3.442619855899
) )
func absInt32(i int32) uint32 { func absInt32(i int32) uint32 {
if i < 0 { if i < 0 {
return uint32(-i) return uint32(-i)
} }
return uint32(i); return uint32(i)
} }
// NormFloat64 returns a normally distributed float64 in the range // NormFloat64 returns a normally distributed float64 in the range
...@@ -37,9 +37,9 @@ func absInt32(i int32) uint32 { ...@@ -37,9 +37,9 @@ func absInt32(i int32) uint32 {
// //
func (r *Rand) NormFloat64() float64 { func (r *Rand) NormFloat64() float64 {
for { for {
j := int32(r.Uint32()); // Possibly negative j := int32(r.Uint32()) // Possibly negative
i := j & 0x7F; i := j & 0x7F
x := float64(j) * float64(wn[i]); x := float64(j) * float64(wn[i])
if absInt32(j) < kn[i] { if absInt32(j) < kn[i] {
// This case should be hit better than 99% of the time. // This case should be hit better than 99% of the time.
return x return x
...@@ -48,8 +48,8 @@ func (r *Rand) NormFloat64() float64 { ...@@ -48,8 +48,8 @@ func (r *Rand) NormFloat64() float64 {
if i == 0 { if i == 0 {
// This extra work is only required for the base strip. // This extra work is only required for the base strip.
for { for {
x = -math.Log(r.Float64()) * (1.0 / rn); x = -math.Log(r.Float64()) * (1.0 / rn)
y := -math.Log(r.Float64()); y := -math.Log(r.Float64())
if y+y >= x*x { if y+y >= x*x {
break break
} }
...@@ -57,13 +57,13 @@ func (r *Rand) NormFloat64() float64 { ...@@ -57,13 +57,13 @@ func (r *Rand) NormFloat64() float64 {
if j > 0 { if j > 0 {
return rn + x return rn + x
} }
return -rn - x; return -rn - x
} }
if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) { if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
return x return x
} }
} }
panic("unreachable"); panic("unreachable")
} }
var kn = [128]uint32{ var kn = [128]uint32{
......
...@@ -10,42 +10,42 @@ import "sync" ...@@ -10,42 +10,42 @@ import "sync"
// A Source represents a source of uniformly-distributed // A Source represents a source of uniformly-distributed
// pseudo-random int64 values in the range [0, 1<<63). // pseudo-random int64 values in the range [0, 1<<63).
type Source interface { type Source interface {
Int63() int64; Int63() int64
Seed(seed int64); Seed(seed int64)
} }
// NewSource returns a new pseudo-random Source seeded with the given value. // NewSource returns a new pseudo-random Source seeded with the given value.
func NewSource(seed int64) Source { func NewSource(seed int64) Source {
var rng rngSource; var rng rngSource
rng.Seed(seed); rng.Seed(seed)
return &rng; return &rng
} }
// A Rand is a source of random numbers. // A Rand is a source of random numbers.
type Rand struct { type Rand struct {
src Source; src Source
} }
// New returns a new Rand that uses random values from src // New returns a new Rand that uses random values from src
// to generate other random values. // to generate other random values.
func New(src Source) *Rand { return &Rand{src} } func New(src Source) *Rand { return &Rand{src} }
// Seed uses the provided seed value to initialize the generator to a deterministic state. // Seed uses the provided seed value to initialize the generator to a deterministic state.
func (r *Rand) Seed(seed int64) { r.src.Seed(seed) } func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (r *Rand) Int63() int64 { return r.src.Int63() } func (r *Rand) Int63() int64 { return r.src.Int63() }
// Uint32 returns a pseudo-random 32-bit value as a uint32. // Uint32 returns a pseudo-random 32-bit value as a uint32.
func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) } func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32. // Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) } func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
// Int returns a non-negative pseudo-random int. // Int returns a non-negative pseudo-random int.
func (r *Rand) Int() int { func (r *Rand) Int() int {
u := uint(r.Int63()); u := uint(r.Int63())
return int(u << 1 >> 1); // clear sign bit if int == int32 return int(u << 1 >> 1) // clear sign bit if int == int32
} }
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
...@@ -53,40 +53,40 @@ func (r *Rand) Int63n(n int64) int64 { ...@@ -53,40 +53,40 @@ func (r *Rand) Int63n(n int64) int64 {
if n <= 0 { if n <= 0 {
return 0 return 0
} }
max := int64((1 << 63) - 1 - (1<<63)%uint64(n)); max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
v := r.Int63(); v := r.Int63()
for v > max { for v > max {
v = r.Int63() v = r.Int63()
} }
return v % n; return v % n
} }
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
func (r *Rand) Int31n(n int32) int32 { return int32(r.Int63n(int64(n))) } func (r *Rand) Int31n(n int32) int32 { return int32(r.Int63n(int64(n))) }
// Intn returns, as an int, a non-negative pseudo-random number in [0,n). // Intn returns, as an int, a non-negative pseudo-random number in [0,n).
func (r *Rand) Intn(n int) int { return int(r.Int63n(int64(n))) } func (r *Rand) Intn(n int) int { return int(r.Int63n(int64(n))) }
// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) } func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float32() float32 { return float32(r.Float64()) } func (r *Rand) Float32() float32 { return float32(r.Float64()) }
// Float returns, as a float, a pseudo-random number in [0.0,1.0). // Float returns, as a float, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float() float { return float(r.Float64()) } func (r *Rand) Float() float { return float(r.Float64()) }
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int { func (r *Rand) Perm(n int) []int {
m := make([]int, n); m := make([]int, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
m[i] = i m[i] = i
} }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
j := r.Intn(i + 1); j := r.Intn(i + 1)
m[i], m[j] = m[j], m[i]; m[i], m[j] = m[j], m[i]
} }
return m; return m
} }
/* /*
...@@ -96,40 +96,40 @@ func (r *Rand) Perm(n int) []int { ...@@ -96,40 +96,40 @@ func (r *Rand) Perm(n int) []int {
var globalRand = New(&lockedSource{src: NewSource(1)}) var globalRand = New(&lockedSource{src: NewSource(1)})
// Seed uses the provided seed value to initialize the generator to a deterministic state. // Seed uses the provided seed value to initialize the generator to a deterministic state.
func Seed(seed int64) { globalRand.Seed(seed) } func Seed(seed int64) { globalRand.Seed(seed) }
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func Int63() int64 { return globalRand.Int63() } func Int63() int64 { return globalRand.Int63() }
// Uint32 returns a pseudo-random 32-bit value as a uint32. // Uint32 returns a pseudo-random 32-bit value as a uint32.
func Uint32() uint32 { return globalRand.Uint32() } func Uint32() uint32 { return globalRand.Uint32() }
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32. // Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
func Int31() int32 { return globalRand.Int31() } func Int31() int32 { return globalRand.Int31() }
// Int returns a non-negative pseudo-random int. // Int returns a non-negative pseudo-random int.
func Int() int { return globalRand.Int() } func Int() int { return globalRand.Int() }
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
func Int63n(n int64) int64 { return globalRand.Int63n(n) } func Int63n(n int64) int64 { return globalRand.Int63n(n) }
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
func Int31n(n int32) int32 { return globalRand.Int31n(n) } func Int31n(n int32) int32 { return globalRand.Int31n(n) }
// Intn returns, as an int, a non-negative pseudo-random number in [0,n). // Intn returns, as an int, a non-negative pseudo-random number in [0,n).
func Intn(n int) int { return globalRand.Intn(n) } func Intn(n int) int { return globalRand.Intn(n) }
// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
func Float64() float64 { return globalRand.Float64() } func Float64() float64 { return globalRand.Float64() }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func Float32() float32 { return globalRand.Float32() } func Float32() float32 { return globalRand.Float32() }
// Float returns, as a float, a pseudo-random number in [0.0,1.0). // Float returns, as a float, a pseudo-random number in [0.0,1.0).
func Float() float { return globalRand.Float() } func Float() float { return globalRand.Float() }
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func Perm(n int) []int { return globalRand.Perm(n) } func Perm(n int) []int { return globalRand.Perm(n) }
// NormFloat64 returns a normally distributed float64 in the range // NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with // [-math.MaxFloat64, +math.MaxFloat64] with
...@@ -139,7 +139,7 @@ func Perm(n int) []int { return globalRand.Perm(n) } ...@@ -139,7 +139,7 @@ func Perm(n int) []int { return globalRand.Perm(n) }
// //
// sample = NormFloat64() * desiredStdDev + desiredMean // sample = NormFloat64() * desiredStdDev + desiredMean
// //
func NormFloat64() float64 { return globalRand.NormFloat64() } func NormFloat64() float64 { return globalRand.NormFloat64() }
// ExpFloat64 returns an exponentially distributed float64 in the range // ExpFloat64 returns an exponentially distributed float64 in the range
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter // (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
...@@ -149,22 +149,22 @@ func NormFloat64() float64 { return globalRand.NormFloat64() } ...@@ -149,22 +149,22 @@ func NormFloat64() float64 { return globalRand.NormFloat64() }
// //
// sample = ExpFloat64() / desiredRateParameter // sample = ExpFloat64() / desiredRateParameter
// //
func ExpFloat64() float64 { return globalRand.ExpFloat64() } func ExpFloat64() float64 { return globalRand.ExpFloat64() }
type lockedSource struct { type lockedSource struct {
lk sync.Mutex; lk sync.Mutex
src Source; src Source
} }
func (r *lockedSource) Int63() (n int64) { func (r *lockedSource) Int63() (n int64) {
r.lk.Lock(); r.lk.Lock()
n = r.src.Int63(); n = r.src.Int63()
r.lk.Unlock(); r.lk.Unlock()
return; return
} }
func (r *lockedSource) Seed(seed int64) { func (r *lockedSource) Seed(seed int64) {
r.lk.Lock(); r.lk.Lock()
r.src.Seed(seed); r.src.Seed(seed)
r.lk.Unlock(); r.lk.Unlock()
} }
This diff is collapsed.
...@@ -12,14 +12,14 @@ package rand ...@@ -12,14 +12,14 @@ package rand
*/ */
const ( const (
_LEN = 607; _LEN = 607
_TAP = 273; _TAP = 273
_MAX = 1 << 63; _MAX = 1 << 63
_MASK = _MAX - 1; _MASK = _MAX - 1
_A = 48271; _A = 48271
_M = (1 << 31) - 1; _M = (1 << 31) - 1
_Q = 44488; _Q = 44488
_R = 3399; _R = 3399
) )
var ( var (
...@@ -179,32 +179,32 @@ var ( ...@@ -179,32 +179,32 @@ var (
4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425, 4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425,
7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134, 7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134,
8382142935188824023, 9103922860780351547, 4152330101494654406, 8382142935188824023, 9103922860780351547, 4152330101494654406,
}; }
) )
type rngSource struct { type rngSource struct {
tap int; // index into vec tap int // index into vec
feed int; // index into vec feed int // index into vec
vec [_LEN]int64; // current feedback register vec [_LEN]int64 // current feedback register
} }
// seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1) // seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1)
func seedrand(x int32) int32 { func seedrand(x int32) int32 {
hi := x / _Q; hi := x / _Q
lo := x % _Q; lo := x % _Q
x = _A*lo - _R*hi; x = _A*lo - _R*hi
if x < 0 { if x < 0 {
x += _M x += _M
} }
return x; return x
} }
// Seed uses the provided seed value to initialize the generator to a deterministic state. // Seed uses the provided seed value to initialize the generator to a deterministic state.
func (rng *rngSource) Seed(seed int64) { func (rng *rngSource) Seed(seed int64) {
rng.tap = 0; rng.tap = 0
rng.feed = _LEN - _TAP; rng.feed = _LEN - _TAP
seed = seed % _M; seed = seed % _M
if seed < 0 { if seed < 0 {
seed += _M seed += _M
} }
...@@ -212,35 +212,35 @@ func (rng *rngSource) Seed(seed int64) { ...@@ -212,35 +212,35 @@ func (rng *rngSource) Seed(seed int64) {
seed = 89482311 seed = 89482311
} }
x := int32(seed); x := int32(seed)
for i := -20; i < _LEN; i++ { for i := -20; i < _LEN; i++ {
x = seedrand(x); x = seedrand(x)
if i >= 0 { if i >= 0 {
var u int64; var u int64
u = int64(x) << 40; u = int64(x) << 40
x = seedrand(x); x = seedrand(x)
u ^= int64(x) << 20; u ^= int64(x) << 20
x = seedrand(x); x = seedrand(x)
u ^= int64(x); u ^= int64(x)
u ^= rng_cooked[i]; u ^= rng_cooked[i]
rng.vec[i] = u & _MASK; rng.vec[i] = u & _MASK
} }
} }
} }
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (rng *rngSource) Int63() int64 { func (rng *rngSource) Int63() int64 {
rng.tap--; rng.tap--
if rng.tap < 0 { if rng.tap < 0 {
rng.tap += _LEN rng.tap += _LEN
} }
rng.feed--; rng.feed--
if rng.feed < 0 { if rng.feed < 0 {
rng.feed += _LEN rng.feed += _LEN
} }
x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK; x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK
rng.vec[rng.feed] = x; rng.vec[rng.feed] = x
return x; return x
} }
This diff is collapsed.
...@@ -12,10 +12,10 @@ package reflect ...@@ -12,10 +12,10 @@ package reflect
// checks in progress are true when it reencounters them. // checks in progress are true when it reencounters them.
// Visited are stored in a map indexed by 17 * a1 + a2; // Visited are stored in a map indexed by 17 * a1 + a2;
type visit struct { type visit struct {
a1 uintptr; a1 uintptr
a2 uintptr; a2 uintptr
typ Type; typ Type
next *visit; next *visit
} }
// Tests for deep equality using reflected types. The map argument tracks // Tests for deep equality using reflected types. The map argument tracks
...@@ -31,8 +31,8 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool { ...@@ -31,8 +31,8 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
// if depth > 10 { panic("deepValueEqual") } // for debugging // if depth > 10 { panic("deepValueEqual") } // for debugging
addr1 := v1.Addr(); addr1 := v1.Addr()
addr2 := v2.Addr(); addr2 := v2.Addr()
if addr1 > addr2 { if addr1 > addr2 {
// Canonicalize order to reduce number of entries in visited. // Canonicalize order to reduce number of entries in visited.
addr1, addr2 = addr2, addr1 addr1, addr2 = addr2, addr1
...@@ -44,9 +44,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool { ...@@ -44,9 +44,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
} }
// ... or already seen // ... or already seen
h := 17*addr1 + addr2; h := 17*addr1 + addr2
seen, _ := visited[h]; seen, _ := visited[h]
typ := v1.Type(); typ := v1.Type()
for p := seen; p != nil; p = p.next { for p := seen; p != nil; p = p.next {
if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ { if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ {
return true return true
...@@ -54,12 +54,12 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool { ...@@ -54,12 +54,12 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
} }
// Remember for later. // Remember for later.
visited[h] = &visit{addr1, addr2, typ, seen}; visited[h] = &visit{addr1, addr2, typ, seen}
switch v := v1.(type) { switch v := v1.(type) {
case *ArrayValue: case *ArrayValue:
arr1 := v; arr1 := v
arr2 := v2.(*ArrayValue); arr2 := v2.(*ArrayValue)
if arr1.Len() != arr2.Len() { if arr1.Len() != arr2.Len() {
return false return false
} }
...@@ -68,10 +68,10 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool { ...@@ -68,10 +68,10 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
return false return false
} }
} }
return true; return true
case *SliceValue: case *SliceValue:
arr1 := v; arr1 := v
arr2 := v2.(*SliceValue); arr2 := v2.(*SliceValue)
if arr1.Len() != arr2.Len() { if arr1.Len() != arr2.Len() {
return false return false
} }
...@@ -80,28 +80,28 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool { ...@@ -80,28 +80,28 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
return false return false
} }
} }
return true; return true
case *InterfaceValue: case *InterfaceValue:
i1 := v.Interface(); i1 := v.Interface()
i2 := v2.Interface(); i2 := v2.Interface()
if i1 == nil || i2 == nil { if i1 == nil || i2 == nil {
return i1 == i2 return i1 == i2
} }
return deepValueEqual(NewValue(i1), NewValue(i2), visited, depth+1); return deepValueEqual(NewValue(i1), NewValue(i2), visited, depth+1)
case *PtrValue: case *PtrValue:
return deepValueEqual(v.Elem(), v2.(*PtrValue).Elem(), visited, depth+1) return deepValueEqual(v.Elem(), v2.(*PtrValue).Elem(), visited, depth+1)
case *StructValue: case *StructValue:
struct1 := v; struct1 := v
struct2 := v2.(*StructValue); struct2 := v2.(*StructValue)
for i, n := 0, v.NumField(); i < n; i++ { for i, n := 0, v.NumField(); i < n; i++ {
if !deepValueEqual(struct1.Field(i), struct2.Field(i), visited, depth+1) { if !deepValueEqual(struct1.Field(i), struct2.Field(i), visited, depth+1) {
return false return false
} }
} }
return true; return true
case *MapValue: case *MapValue:
map1 := v; map1 := v
map2 := v2.(*MapValue); map2 := v2.(*MapValue)
if map1.Len() != map2.Len() { if map1.Len() != map2.Len() {
return false return false
} }
...@@ -110,13 +110,13 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool { ...@@ -110,13 +110,13 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
return false return false
} }
} }
return true; return true
default: default:
// Normal equality suffices // Normal equality suffices
return v1.Interface() == v2.Interface() return v1.Interface() == v2.Interface()
} }
panic("Not reached"); panic("Not reached")
} }
// DeepEqual tests for deep equality. It uses normal == equality where possible // DeepEqual tests for deep equality. It uses normal == equality where possible
...@@ -126,10 +126,10 @@ func DeepEqual(a1, a2 interface{}) bool { ...@@ -126,10 +126,10 @@ func DeepEqual(a1, a2 interface{}) bool {
if a1 == nil || a2 == nil { if a1 == nil || a2 == nil {
return a1 == a2 return a1 == a2
} }
v1 := NewValue(a1); v1 := NewValue(a1)
v2 := NewValue(a2); v2 := NewValue(a2)
if v1.Type() != v2.Type() { if v1.Type() != v2.Type() {
return false return false
} }
return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0); return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0)
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -10,10 +10,10 @@ package rpc ...@@ -10,10 +10,10 @@ package rpc
*/ */
import ( import (
"fmt"; "fmt"
"http"; "http"
"sort"; "sort"
"template"; "template"
) )
const debugText = `<html> const debugText = `<html>
...@@ -39,47 +39,47 @@ const debugText = `<html> ...@@ -39,47 +39,47 @@ const debugText = `<html>
var debug = template.MustParse(debugText, nil) var debug = template.MustParse(debugText, nil)
type debugMethod struct { type debugMethod struct {
m *methodType; m *methodType
name string; name string
} }
type methodArray []debugMethod type methodArray []debugMethod
type debugService struct { type debugService struct {
s *service; s *service
name string; name string
meth methodArray; meth methodArray
} }
type serviceArray []debugService type serviceArray []debugService
func (s serviceArray) Len() int { return len(s) } func (s serviceArray) Len() int { return len(s) }
func (s serviceArray) Less(i, j int) bool { return s[i].name < s[j].name } func (s serviceArray) Less(i, j int) bool { return s[i].name < s[j].name }
func (s serviceArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s serviceArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (m methodArray) Len() int { return len(m) } func (m methodArray) Len() int { return len(m) }
func (m methodArray) Less(i, j int) bool { return m[i].name < m[j].name } func (m methodArray) Less(i, j int) bool { return m[i].name < m[j].name }
func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] } func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
// Runs at /debug/rpc // Runs at /debug/rpc
func debugHTTP(c *http.Conn, req *http.Request) { func debugHTTP(c *http.Conn, req *http.Request) {
// Build a sorted version of the data. // Build a sorted version of the data.
var services = make(serviceArray, len(server.serviceMap)); var services = make(serviceArray, len(server.serviceMap))
i := 0; i := 0
server.Lock(); server.Lock()
for sname, service := range server.serviceMap { for sname, service := range server.serviceMap {
services[i] = debugService{service, sname, make(methodArray, len(service.method))}; services[i] = debugService{service, sname, make(methodArray, len(service.method))}
j := 0; j := 0
for mname, method := range service.method { for mname, method := range service.method {
services[i].meth[j] = debugMethod{method, mname}; services[i].meth[j] = debugMethod{method, mname}
j++; j++
} }
sort.Sort(services[i].meth); sort.Sort(services[i].meth)
i++; i++
} }
server.Unlock(); server.Unlock()
sort.Sort(services); sort.Sort(services)
err := debug.Execute(services, c); err := debug.Execute(services, c)
if err != nil { if err != nil {
fmt.Fprintln(c, "rpc: error executing template:", err.String()) fmt.Fprintln(c, "rpc: error executing template:", err.String())
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment