Commit bf67a7b9 authored by Russ Cox's avatar Russ Cox

build: fix build

I said rm, but not hg rm.
I never was good at Simon says.

TBR=bradfitz
CC=golang-dev
https://golang.org/cl/5574066
parent cf09a9d3
include ../../../Make.inc
TARG=net/dict
GOFILES=\
dict.go\
include ../../../Make.pkg
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package dict implements the Dictionary Server Protocol
// as defined in RFC 2229.
package dict
import (
"net/textproto"
"strconv"
"strings"
)
// A Client represents a client connection to a dictionary server.
type Client struct {
text *textproto.Conn
}
// Dial returns a new client connected to a dictionary server at
// addr on the given network.
func Dial(network, addr string) (*Client, error) {
text, err := textproto.Dial(network, addr)
if err != nil {
return nil, err
}
_, _, err = text.ReadCodeLine(220)
if err != nil {
text.Close()
return nil, err
}
return &Client{text: text}, nil
}
// Close closes the connection to the dictionary server.
func (c *Client) Close() error {
return c.text.Close()
}
// A Dict represents a dictionary available on the server.
type Dict struct {
Name string // short name of dictionary
Desc string // long description
}
// Dicts returns a list of the dictionaries available on the server.
func (c *Client) Dicts() ([]Dict, error) {
id, err := c.text.Cmd("SHOW DB")
if err != nil {
return nil, err
}
c.text.StartResponse(id)
defer c.text.EndResponse(id)
_, _, err = c.text.ReadCodeLine(110)
if err != nil {
return nil, err
}
lines, err := c.text.ReadDotLines()
if err != nil {
return nil, err
}
_, _, err = c.text.ReadCodeLine(250)
dicts := make([]Dict, len(lines))
for i := range dicts {
d := &dicts[i]
a, _ := fields(lines[i])
if len(a) < 2 {
return nil, textproto.ProtocolError("invalid dictionary: " + lines[i])
}
d.Name = a[0]
d.Desc = a[1]
}
return dicts, err
}
// A Defn represents a definition.
type Defn struct {
Dict Dict // Dict where definition was found
Word string // Word being defined
Text []byte // Definition text, typically multiple lines
}
// Define requests the definition of the given word.
// The argument dict names the dictionary to use,
// the Name field of a Dict returned by Dicts.
//
// The special dictionary name "*" means to look in all the
// server's dictionaries.
// The special dictionary name "!" means to look in all the
// server's dictionaries in turn, stopping after finding the word
// in one of them.
func (c *Client) Define(dict, word string) ([]*Defn, error) {
id, err := c.text.Cmd("DEFINE %s %q", dict, word)
if err != nil {
return nil, err
}
c.text.StartResponse(id)
defer c.text.EndResponse(id)
_, line, err := c.text.ReadCodeLine(150)
if err != nil {
return nil, err
}
a, _ := fields(line)
if len(a) < 1 {
return nil, textproto.ProtocolError("malformed response: " + line)
}
n, err := strconv.Atoi(a[0])
if err != nil {
return nil, textproto.ProtocolError("invalid definition count: " + a[0])
}
def := make([]*Defn, n)
for i := 0; i < n; i++ {
_, line, err = c.text.ReadCodeLine(151)
if err != nil {
return nil, err
}
a, _ := fields(line)
if len(a) < 3 {
// skip it, to keep protocol in sync
i--
n--
def = def[0:n]
continue
}
d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}}
d.Text, err = c.text.ReadDotBytes()
if err != nil {
return nil, err
}
def[i] = d
}
_, _, err = c.text.ReadCodeLine(250)
return def, err
}
// Fields returns the fields in s.
// Fields are space separated unquoted words
// or quoted with single or double quote.
func fields(s string) ([]string, error) {
var v []string
i := 0
for {
for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
i++
}
if i >= len(s) {
break
}
if s[i] == '"' || s[i] == '\'' {
q := s[i]
// quoted string
var j int
for j = i + 1; ; j++ {
if j >= len(s) {
return nil, textproto.ProtocolError("malformed quoted string")
}
if s[j] == '\\' {
j++
continue
}
if s[j] == q {
j++
break
}
}
v = append(v, unquote(s[i+1:j-1]))
i = j
} else {
// atom
var j int
for j = i; j < len(s); j++ {
if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' {
break
}
}
v = append(v, s[i:j])
i = j
}
if i < len(s) {
c := s[i]
if c != ' ' && c != '\t' {
return nil, textproto.ProtocolError("quotes not on word boundaries")
}
}
}
return v, nil
}
func unquote(s string) string {
if strings.Index(s, "\\") < 0 {
return s
}
b := []byte(s)
w := 0
for r := 0; r < len(b); r++ {
c := b[r]
if c == '\\' {
r++
c = b[r]
}
b[w] = c
w++
}
return string(b[0:w])
}
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../Make.inc
TARG=patch
GOFILES=\
apply.go\
git.go\
patch.go\
textdiff.go\
include ../../Make.pkg
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package patch
import "os"
// An Op is a single operation to execute to apply a patch.
type Op struct {
Verb Verb // action
Src string // source file
Dst string // destination file
Mode int // mode for destination (if non-zero)
Data []byte // data for destination (if non-nil)
}
// Apply applies the patch set to the files named in the patch set,
// constructing an in-memory copy of the new file state.
// It is the client's job to write the changes to the file system
// if desired.
//
// The function readFile should return the contents of the named file.
// Typically this function will be io.ReadFile.
//
func (set *Set) Apply(readFile func(string) ([]byte, error)) ([]Op, error) {
op := make([]Op, len(set.File))
for i, f := range set.File {
o := &op[i]
o.Verb = f.Verb
o.Src = f.Src
o.Dst = f.Dst
o.Mode = f.NewMode
if f.Diff != NoDiff || o.Verb != Edit {
// Clients assume o.Data == nil means no data diff.
// Start with a non-nil data.
var old []byte = make([]byte, 0) // not nil
var err error
if f.Src != "" {
old, err = readFile(f.Src)
if err != nil {
return nil, &os.PathError{string(f.Verb), f.Src, err}
}
}
o.Data, err = f.Diff.Apply(old)
if err != nil {
return nil, &os.PathError{string(f.Verb), f.Src, err}
}
}
}
return op, nil
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package patch
import (
"bytes"
"compress/zlib"
"crypto/sha1"
"encoding/git85"
"errors"
"fmt"
"io"
)
func gitSHA1(data []byte) []byte {
if len(data) == 0 {
// special case: 0 length is all zeros sum
return make([]byte, 20)
}
h := sha1.New()
fmt.Fprintf(h, "blob %d\x00", len(data))
h.Write(data)
return h.Sum(nil)
}
// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
// GitBinaryLiteral represents a Git binary literal diff.
type GitBinaryLiteral struct {
OldSHA1 []byte // if non-empty, the SHA1 hash of the original
New []byte // the new contents
}
// Apply implements the Diff interface's Apply method.
func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, error) {
if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
return nil, ErrPatchFailure
}
return d.New, nil
}
func unhex(c byte) uint8 {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 255
}
func getHex(s []byte) (data []byte, rest []byte) {
n := 0
for n < len(s) && unhex(s[n]) != 255 {
n++
}
n &^= 1 // Only take an even number of hex digits.
data = make([]byte, n/2)
for i := range data {
data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
}
rest = s[n:]
return
}
// ParseGitBinary parses raw as a Git binary patch.
func ParseGitBinary(raw []byte) (Diff, error) {
var oldSHA1, newSHA1 []byte
var sawBinary bool
for {
var first []byte
first, raw, _ = getLine(raw, 1)
first = bytes.TrimSpace(first)
if s, ok := skip(first, "index "); ok {
oldSHA1, s = getHex(s)
if s, ok = skip(s, ".."); !ok {
continue
}
newSHA1, s = getHex(s)
continue
}
if _, ok := skip(first, "GIT binary patch"); ok {
sawBinary = true
continue
}
if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
data := make([]byte, n)
d := git85.NewDecoder(bytes.NewBuffer(raw))
z, err := zlib.NewReader(d)
if err != nil {
return nil, err
}
defer z.Close()
if _, err = io.ReadFull(z, data); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return nil, err
}
var buf [1]byte
m, err := z.Read(buf[0:])
if m != 0 || err != io.EOF {
return nil, errors.New("Git binary literal longer than expected")
}
if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
return nil, errors.New("Git binary literal SHA1 mismatch")
}
return &GitBinaryLiteral{oldSHA1, data}, nil
}
if !sawBinary {
return nil, errors.New("unexpected Git patch header: " + string(first))
}
}
panic("unreachable")
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package patch implements parsing and execution of the textual and
// binary patch descriptions used by version control tools such as
// CVS, Git, Mercurial, and Subversion.
package patch
import (
"bytes"
"path"
"strings"
)
// A Set represents a set of patches to be applied as a single atomic unit.
// Patch sets are often preceded by a descriptive header.
type Set struct {
Header string // free-form text
File []*File
}
// A File represents a collection of changes to be made to a single file.
type File struct {
Verb Verb
Src string // source for Verb == Copy, Verb == Rename
Dst string
OldMode, NewMode int // 0 indicates not used
Diff // changes to data; == NoDiff if operation does not edit file
}
// A Verb is an action performed on a file.
type Verb string
const (
Add Verb = "add"
Copy Verb = "copy"
Delete Verb = "delete"
Edit Verb = "edit"
Rename Verb = "rename"
)
// A Diff is any object that describes changes to transform
// an old byte stream to a new one.
type Diff interface {
// Apply applies the changes listed in the diff
// to the string s, returning the new version of the string.
// Note that the string s need not be a text string.
Apply(old []byte) (new []byte, err error)
}
// NoDiff is a no-op Diff implementation: it passes the
// old data through unchanged.
var NoDiff Diff = noDiffType(0)
type noDiffType int
func (noDiffType) Apply(old []byte) ([]byte, error) {
return old, nil
}
// A SyntaxError represents a syntax error encountered while parsing a patch.
type SyntaxError string
func (e SyntaxError) Error() string { return string(e) }
var newline = []byte{'\n'}
// Parse patches the patch text to create a patch Set.
// The patch text typically comprises a textual header and a sequence
// of file patches, as would be generated by CVS, Subversion,
// Mercurial, or Git.
func Parse(text []byte) (*Set, error) {
// Split text into files.
// CVS and Subversion begin new files with
// Index: file name.
// ==================
// diff -u blah blah
//
// Mercurial and Git use
// diff [--git] a/file/path b/file/path.
//
// First look for Index: lines. If none, fall back on diff lines.
text, files := sections(text, "Index: ")
if len(files) == 0 {
text, files = sections(text, "diff ")
}
set := &Set{string(text), make([]*File, len(files))}
// Parse file header and then
// parse files into patch chunks.
// Each chunk begins with @@.
for i, raw := range files {
p := new(File)
set.File[i] = p
// First line of hdr is the Index: that
// begins the section. After that is the file name.
s, raw, _ := getLine(raw, 1)
if hasPrefix(s, "Index: ") {
p.Dst = string(bytes.TrimSpace(s[7:]))
goto HaveName
} else if hasPrefix(s, "diff ") {
str := string(bytes.TrimSpace(s))
i := strings.LastIndex(str, " b/")
if i >= 0 {
p.Dst = str[i+3:]
goto HaveName
}
}
return nil, SyntaxError("unexpected patch header line: " + string(s))
HaveName:
p.Dst = path.Clean(p.Dst)
if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
return nil, SyntaxError("invalid path: " + p.Dst)
}
// Parse header lines giving file information:
// new file mode %o - file created
// deleted file mode %o - file deleted
// old file mode %o - file mode changed
// new file mode %o - file mode changed
// rename from %s - file renamed from other file
// rename to %s
// copy from %s - file copied from other file
// copy to %s
p.Verb = Edit
for len(raw) > 0 {
oldraw := raw
var l []byte
l, raw, _ = getLine(raw, 1)
l = bytes.TrimSpace(l)
if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
p.NewMode = m
p.Verb = Add
continue
}
if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
p.OldMode = m
p.Verb = Delete
p.Src = p.Dst
p.Dst = ""
continue
}
if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
// usually implies p.Verb = "rename" or "copy"
// but we'll get that from the rename or copy line.
p.OldMode = m
continue
}
if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
p.OldMode = m
continue
}
if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
p.NewMode = m
continue
}
if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
p.Src = string(s)
p.Verb = Rename
continue
}
if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
p.Verb = Rename
continue
}
if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
p.Src = string(s)
p.Verb = Copy
continue
}
if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
p.Verb = Copy
continue
}
if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
// Hg prints
// Binary file foo has changed
// when deleting a binary file.
continue
}
if s, ok := skip(l, "RCS file: "); ok && len(s) > 0 {
// CVS prints
// RCS file: /cvs/plan9/bin/yesterday,v
// retrieving revision 1.1
// for each file.
continue
}
if s, ok := skip(l, "retrieving revision "); ok && len(s) > 0 {
// CVS prints
// RCS file: /cvs/plan9/bin/yesterday,v
// retrieving revision 1.1
// for each file.
continue
}
if hasPrefix(l, "===") || hasPrefix(l, "---") || hasPrefix(l, "+++") || hasPrefix(l, "diff ") {
continue
}
if hasPrefix(l, "@@ -") {
diff, err := ParseTextDiff(oldraw)
if err != nil {
return nil, err
}
p.Diff = diff
break
}
if hasPrefix(l, "GIT binary patch") || (hasPrefix(l, "index ") && !hasPrefix(raw, "--- ")) {
diff, err := ParseGitBinary(oldraw)
if err != nil {
return nil, err
}
p.Diff = diff
break
}
if hasPrefix(l, "index ") {
continue
}
return nil, SyntaxError("unexpected patch header line: " + string(l))
}
if p.Diff == nil {
p.Diff = NoDiff
}
if p.Verb == Edit {
p.Src = p.Dst
}
}
return set, nil
}
// getLine returns the first n lines of data and the remainder.
// If data has no newline, getLine returns data, nil, false
func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
rest = data
ok = true
for ; n > 0; n-- {
nl := bytes.Index(rest, newline)
if nl < 0 {
rest = nil
ok = false
break
}
rest = rest[nl+1:]
}
first = data[0 : len(data)-len(rest)]
return
}
// sections returns a collection of file sections,
// each of which begins with a line satisfying prefix.
// text before the first instance of such a line is
// returned separately.
func sections(text []byte, prefix string) ([]byte, [][]byte) {
n := 0
for b := text; ; {
if hasPrefix(b, prefix) {
n++
}
nl := bytes.Index(b, newline)
if nl < 0 {
break
}
b = b[nl+1:]
}
sect := make([][]byte, n+1)
n = 0
for b := text; ; {
if hasPrefix(b, prefix) {
sect[n] = text[0 : len(text)-len(b)]
n++
text = b
}
nl := bytes.Index(b, newline)
if nl < 0 {
sect[n] = text
break
}
b = b[nl+1:]
}
return sect[0], sect[1:]
}
// if s begins with the prefix t, skip returns
// s with that prefix removed and ok == true.
func skip(s []byte, t string) (ss []byte, ok bool) {
if len(s) < len(t) || string(s[0:len(t)]) != t {
return nil, false
}
return s[len(t):], true
}
// if s begins with the prefix t and then is a sequence
// of digits in the given base, atoi returns the number
// represented by the digits and s with the
// prefix and the digits removed.
func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) {
if s, ok = skip(s, t); !ok {
return
}
var i int
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
n = n*base + int(s[i]-'0')
}
if i == 0 {
return
}
return n, s[i:], true
}
// hasPrefix returns true if s begins with t.
func hasPrefix(s []byte, t string) bool {
_, ok := skip(s, t)
return ok
}
// splitLines returns the result of splitting s into lines.
// The \n on each line is preserved.
func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline) }
This diff is collapsed.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package patch
import (
"bytes"
"errors"
)
type TextDiff []TextChunk
// A TextChunk specifies an edit to a section of a file:
// the text beginning at Line, which should be exactly Old,
// is to be replaced with New.
type TextChunk struct {
Line int
Old []byte
New []byte
}
func ParseTextDiff(raw []byte) (TextDiff, error) {
var chunkHeader []byte
// Copy raw so it is safe to keep references to slices.
_, chunks := sections(raw, "@@ -")
delta := 0
diff := make(TextDiff, len(chunks))
for i, raw := range chunks {
c := &diff[i]
// Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
chunk := splitLines(raw)
chunkHeader = chunk[0]
var ok bool
var oldLine, oldCount, newLine, newCount int
s := chunkHeader
if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
goto ErrChunkHdr
}
if len(s) == 0 || s[0] != ',' {
oldCount = 1
} else if oldCount, s, ok = atoi(s, ",", 10); !ok {
goto ErrChunkHdr
}
if newLine, s, ok = atoi(s, " +", 10); !ok {
goto ErrChunkHdr
}
if len(s) == 0 || s[0] != ',' {
newCount = 1
} else if newCount, s, ok = atoi(s, ",", 10); !ok {
goto ErrChunkHdr
}
if !hasPrefix(s, " @@") {
goto ErrChunkHdr
}
// Special case: for created or deleted files, the empty half
// is given as starting at line 0. Translate to line 1.
if oldCount == 0 && oldLine == 0 {
oldLine = 1
}
if newCount == 0 && newLine == 0 {
newLine = 1
}
// Count lines in text
var dropOldNL, dropNewNL bool
var nold, nnew int
var lastch byte
chunk = chunk[1:]
for _, l := range chunk {
if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
if len(bytes.TrimSpace(l)) != 0 {
return nil, SyntaxError("too many chunk lines")
}
continue
}
if len(l) == 0 {
return nil, SyntaxError("empty chunk line")
}
switch l[0] {
case '+':
nnew++
case '-':
nold++
case ' ':
nnew++
nold++
case '\\':
if _, ok := skip(l, "\\ No newline at end of file"); ok {
switch lastch {
case '-':
dropOldNL = true
case '+':
dropNewNL = true
case ' ':
dropOldNL = true
dropNewNL = true
default:
return nil, SyntaxError("message `\\ No newline at end of file' out of context")
}
break
}
fallthrough
default:
return nil, SyntaxError("unexpected chunk line: " + string(l))
}
lastch = l[0]
}
// Does it match the header?
if nold != oldCount || nnew != newCount {
return nil, SyntaxError("chunk header does not match line count: " + string(chunkHeader))
}
if oldLine+delta != newLine {
return nil, SyntaxError("chunk delta is out of sync with previous chunks")
}
delta += nnew - nold
c.Line = oldLine
var old, new bytes.Buffer
nold = 0
nnew = 0
for _, l := range chunk {
if nold == oldCount && nnew == newCount {
break
}
ch, l := l[0], l[1:]
if ch == '\\' {
continue
}
if ch != '+' {
old.Write(l)
nold++
}
if ch != '-' {
new.Write(l)
nnew++
}
}
c.Old = old.Bytes()
c.New = new.Bytes()
if dropOldNL {
c.Old = c.Old[0 : len(c.Old)-1]
}
if dropNewNL {
c.New = c.New[0 : len(c.New)-1]
}
}
return diff, nil
ErrChunkHdr:
return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
}
var ErrPatchFailure = errors.New("patch did not apply cleanly")
// Apply applies the changes listed in the diff
// to the data, returning the new version.
func (d TextDiff) Apply(data []byte) ([]byte, error) {
var buf bytes.Buffer
line := 1
for _, c := range d {
var ok bool
var prefix []byte
prefix, data, ok = getLine(data, c.Line-line)
if !ok || !bytes.HasPrefix(data, c.Old) {
return nil, ErrPatchFailure
}
buf.Write(prefix)
data = data[len(c.Old):]
buf.Write(c.New)
line = c.Line + bytes.Count(c.Old, newline)
}
buf.Write(data)
return buf.Bytes(), nil
}
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