Commit 34fbc01d authored by ale's avatar ale
Browse files

update Godeps

parent fed952b8
......@@ -9,14 +9,18 @@
"ImportPath": "github.com/PuerkitoBio/ghost",
"Rev": "a0146f2f931611b8bfe40f07018c97a7c881c76a"
},
{
"ImportPath": "github.com/aryann/difflib",
"Rev": "035af7c09b120b0909dd998c92745b82f61e0b1c"
},
{
"ImportPath": "github.com/cactus/go-statsd-client/statsd",
"Rev": "a99092dcd2d2f2a604a6f2502ba9ebba6a1165e5"
},
{
"ImportPath": "github.com/coreos/go-etcd/etcd",
"Comment": "v0.2.0-rc1-127-g6fe04d5",
"Rev": "6fe04d580dfb71c9e34cbce2f4df9eefd1e1241e"
"Comment": "v2.0.0-22-g9847b93",
"Rev": "9847b93751a5fbaf227b893d172cee0104ac6427"
},
{
"ImportPath": "github.com/garyburd/redigo/redis",
......@@ -40,11 +44,15 @@
},
{
"ImportPath": "github.com/miekg/dns",
"Rev": "3f504e8dabd5d562e997d19ce0200aa41973e1b2"
"Rev": "fd694e564b3ceaf34a8bbe9ef18f65c64df8ed03"
},
{
"ImportPath": "github.com/nu7hatch/gouuid",
"Rev": "179d4d0c4d8d407a32af483c2354df1d2c91e6c3"
},
{
"ImportPath": "github.com/ugorji/go/codec",
"Rev": "03e33114d4d60a1f37150325e15f51b0fa6fc4f6"
}
]
}
difflib
=======
difflib is a simple library written in [Go](http://golang.org/) for
diffing two sequences of text.
Installing
----------
To install, issue:
go get github.com/aryann/difflib
Using
-----
To start using difflib, create a new file in your workspace and import
difflib:
import (
...
"fmt"
"github.com/aryann/difflib"
...
)
Then call either `difflib.Diff` or `difflib.HTMLDiff`:
fmt.Println(difflib.HTMLDiff([]string{"one", "two", "three"}, []string{"two", "four", "three"}))
If you'd like more control over the output, see how the function
`HTMLDiff` relies on `Diff` in difflib.go.
Running the Demo
----------------
There is a demo application in the difflib_demo directory. To run it,
navigate to your `$GOPATH` and run:
go run src/github.com/aryann/difflib/difflib_server/difflib_demo.go <file-1> <file-2>
Where `<file-1>` and `<file-2>` are two text files you'd like to
diff. The demo will launch a web server that will contain a table of
the diff results.
// Copyright 2012 Aryan Naraghi (aryan.naraghi@gmail.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package difflib provides functionality for computing the difference
// between two sequences of strings.
package difflib
import (
"bytes"
"fmt"
"math"
)
// DeltaType describes the relationship of elements in two
// sequences. The following table provides a summary:
//
// Constant Code Meaning
// ---------- ------ ---------------------------------------
// Common " " The element occurs in both sequences.
// LeftOnly "-" The element is unique to sequence 1.
// RightOnly "+" The element is unique to sequence 2.
type DeltaType int
const (
Common DeltaType = iota
LeftOnly
RightOnly
)
// String returns a string representation for DeltaType.
func (t DeltaType) String() string {
switch t {
case Common:
return " "
case LeftOnly:
return "-"
case RightOnly:
return "+"
}
return "?"
}
type DiffRecord struct {
Payload string
Delta DeltaType
}
// String returns a string representation of d. The string is a
// concatenation of the delta type and the payload.
func (d DiffRecord) String() string {
return fmt.Sprintf("%s %s", d.Delta, d.Payload)
}
// Diff returns the result of diffing the seq1 and seq2.
func Diff(seq1, seq2 []string) (diff []DiffRecord) {
// Trims any common elements at the heads and tails of the
// sequences before running the diff algorithm. This is an
// optimization.
start, end := numEqualStartAndEndElements(seq1, seq2)
for _, content := range seq1[:start] {
diff = append(diff, DiffRecord{content, Common})
}
diffRes := compute(seq1[start:len(seq1)-end], seq2[start:len(seq2)-end])
diff = append(diff, diffRes...)
for _, content := range seq1[len(seq1)-end:] {
diff = append(diff, DiffRecord{content, Common})
}
return
}
// HTMLDiff returns the results of diffing seq1 and seq2 as an HTML
// string. The resulting HTML is a table without the opening and
// closing table tags. Each table row represents a DiffRecord. The
// first and last columns contain the "line numbers" for seq1 and
// seq2, respectively (the function assumes that seq1 and seq2
// represent the lines in a file). The second and third columns
// contain the actual file contents.
//
// The cells that contain line numbers are decorated with the class
// "line-num". The cells that contain deleted elements are decorated
// with "deleted" and the cells that contain added elements are
// decorated with "added".
func HTMLDiff(seq1, seq2 []string) string {
buf := bytes.NewBufferString("")
i, j := 0, 0
for _, d := range Diff(seq1, seq2) {
buf.WriteString(`<tr><td class="line-num">`)
if d.Delta == Common || d.Delta == LeftOnly {
i++
fmt.Fprintf(buf, "%d</td><td", i)
if d.Delta == LeftOnly {
fmt.Fprint(buf, ` class="deleted"`)
}
fmt.Fprintf(buf, "><pre>%s</pre>", d.Payload)
} else {
buf.WriteString("</td><td>")
}
buf.WriteString("</td><td")
if d.Delta == Common || d.Delta == RightOnly {
j++
if d.Delta == RightOnly {
fmt.Fprint(buf, ` class="added"`)
}
fmt.Fprintf(buf, `><pre>%s</pre></td><td class="line-num">%d`, d.Payload, j)
} else {
buf.WriteString("></td><td>")
}
buf.WriteString("</td></tr>\n")
}
return buf.String()
}
// numEqualStartAndEndElements returns the number of elements a and b
// have in common from the beginning and from the end. If a and b are
// equal, start will equal len(a) == len(b) and end will be zero.
func numEqualStartAndEndElements(seq1, seq2 []string) (start, end int) {
for start < len(seq1) && start < len(seq2) && seq1[start] == seq2[start] {
start++
}
i, j := len(seq1)-1, len(seq2)-1
for i > start && j > start && seq1[i] == seq2[j] {
i--
j--
end++
}
return
}
// intMatrix returns a 2-dimensional slice of ints with the given
// number of rows and columns.
func intMatrix(rows, cols int) [][]int {
matrix := make([][]int, rows)
for i := 0; i < rows; i++ {
matrix[i] = make([]int, cols)
}
return matrix
}
// longestCommonSubsequenceMatrix returns the table that results from
// applying the dynamic programming approach for finding the longest
// common subsequence of seq1 and seq2.
func longestCommonSubsequenceMatrix(seq1, seq2 []string) [][]int {
matrix := intMatrix(len(seq1)+1, len(seq2)+1)
for i := 1; i < len(matrix); i++ {
for j := 1; j < len(matrix[i]); j++ {
if seq1[len(seq1)-i] == seq2[len(seq2)-j] {
matrix[i][j] = matrix[i-1][j-1] + 1
} else {
matrix[i][j] = int(math.Max(float64(matrix[i-1][j]),
float64(matrix[i][j-1])))
}
}
}
return matrix
}
// compute is the unexported helper for Diff that returns the results of
// diffing left and right.
func compute(seq1, seq2 []string) (diff []DiffRecord) {
matrix := longestCommonSubsequenceMatrix(seq1, seq2)
i, j := len(seq1), len(seq2)
for i > 0 || j > 0 {
if i > 0 && matrix[i][j] == matrix[i-1][j] {
diff = append(diff, DiffRecord{seq1[len(seq1)-i], LeftOnly})
i--
} else if j > 0 && matrix[i][j] == matrix[i][j-1] {
diff = append(diff, DiffRecord{seq2[len(seq2)-j], RightOnly})
j--
} else if i > 0 && j > 0 {
diff = append(diff, DiffRecord{seq1[len(seq1)-i], Common})
i--
j--
}
}
return
}
// Copyright 2012 Aryan Naraghi (aryan.naraghi@gmail.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// A demo for difflib. This program accepts the paths to two files and
// launches a web server at port 8080 that serves the diff results.
package main
import (
"fmt"
"github.com/aryann/difflib"
"html"
"html/template"
"io/ioutil"
"net/http"
"os"
"strings"
)
var hostPort = "localhost:8080"
var templateString = `
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>difflib results</title>
<style type="text/css">
table {
background-color: lightgrey;
border-spacing: 1px;
}
tr {
background-color: white;
border-bottom: 1px solid black;
}
.line-num {
width: 50px;
}
.added {
background-color: green;
}
.deleted {
background-color: red;
}
</style>
</head>
<body>
<table>
<tr>
<th></th>
<th><em>{{.Filename1}}</em></th>
<th><em>{{.Filename2}}</em></th>
<th></th>
</tr>
{{.Diff}}
</table>
</body>
</html>
`
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "USAGE: %s <file-1> <file-2>\n", os.Args[0])
os.Exit(1)
}
http.HandleFunc("/", diffHandler(os.Args[1], os.Args[2]))
fmt.Printf("Starting server at %s.\n", hostPort)
err := http.ListenAndServe(hostPort, nil)
if err != nil {
panic(err)
}
}
// diffHandler returns an http.HandlerFunc that serves the diff of the
// two given files.
func diffHandler(filename1, filename2 string) http.HandlerFunc {
diff := difflib.HTMLDiff(fileToLines(filename1), fileToLines(filename2))
tmpl, _ := template.New("diffTemplate").Parse(templateString)
return func(w http.ResponseWriter, r *http.Request) {
err := tmpl.Execute(w, map[string]interface{}{
"Diff": template.HTML(diff),
"Filename1": filename1,
"Filename2": filename2,
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
// filesToLines takes a path to a file and returns a string array of
// the lines in the file. Any HTML in the file is escaped.
func fileToLines(filename string) []string {
contents, _ := ioutil.ReadFile(filename)
return strings.Split(html.EscapeString(string(contents)), "\n")
}
// Copyright 2012 Aryan Naraghi (aryan.naraghi@gmail.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package difflib
import (
"reflect"
"strings"
"testing"
)
var lcsTests = []struct {
seq1 string
seq2 string
lcs int
}{
{"", "", 0},
{"abc", "abc", 3},
{"mzjawxu", "xmjyauz", 4},
{"human", "chimpanzee", 4},
{"Hello, world!", "Hello, world!", 13},
{"Hello, world!", "H e l l o , w o r l d !", 13},
}
func TestLongestCommonSubsequenceMatrix(t *testing.T) {
for i, test := range lcsTests {
seq1 := strings.Split(test.seq1, "")
seq2 := strings.Split(test.seq2, "")
matrix := longestCommonSubsequenceMatrix(seq1, seq2)
lcs := matrix[len(matrix)-1][len(matrix[0])-1] // Grabs the lower, right value.
if lcs != test.lcs {
t.Errorf("%d. longestCommonSubsequence(%v, %v)[last][last] => %d, expected %d",
i, seq1, seq2, lcs, test.lcs)
}
}
}
var numEqualStartAndEndElementsTests = []struct {
seq1 string
seq2 string
start int
end int
}{
{"", "", 0, 0},
{"abc", "", 0, 0},
{"", "abc", 0, 0},
{"abc", "abc", 3, 0},
{"abhelloc", "abbyec", 2, 1},
{"abchello", "abcbye", 3, 0},
{"helloabc", "byeabc", 0, 3},
}
func TestNumEqualStartAndEndElements(t *testing.T) {
for i, test := range numEqualStartAndEndElementsTests {
seq1 := strings.Split(test.seq1, "")
seq2 := strings.Split(test.seq2, "")
start, end := numEqualStartAndEndElements(seq1, seq2)
if start != test.start || end != test.end {
t.Errorf("%d. numEqualStartAndEndElements(%v, %v) => (%d, %d), expected (%d, %d)",
i, seq1, seq2, start, end, test.start, test.end)
}
}
}
var diffTests = []struct {
Seq1 string
Seq2 string
Diff []DiffRecord
HtmlDiff string
}{
{
"",
"",
[]DiffRecord{
{"", Common},
},
`<tr><td class="line-num">1</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">1</td></tr>
`,
},
{
"same",
"same",
[]DiffRecord{
{"same", Common},
},
`<tr><td class="line-num">1</td><td><pre>same</pre></td><td><pre>same</pre></td><td class="line-num">1</td></tr>
`,
},
{
`one
two
three
`,
`one
two
three
`,
[]DiffRecord{
{"one", Common},
{"two", Common},
{"three", Common},
{"", Common},
},
`<tr><td class="line-num">1</td><td><pre>one</pre></td><td><pre>one</pre></td><td class="line-num">1</td></tr>
<tr><td class="line-num">2</td><td><pre>two</pre></td><td><pre>two</pre></td><td class="line-num">2</td></tr>
<tr><td class="line-num">3</td><td><pre>three</pre></td><td><pre>three</pre></td><td class="line-num">3</td></tr>
<tr><td class="line-num">4</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">4</td></tr>
`,
},
{
`one
two
three
`,
`one
five
three
`,
[]DiffRecord{
{"one", Common},
{"two", LeftOnly},
{"five", RightOnly},
{"three", Common},
{"", Common},
},
`<tr><td class="line-num">1</td><td><pre>one</pre></td><td><pre>one</pre></td><td class="line-num">1</td></tr>
<tr><td class="line-num">2</td><td class="deleted"><pre>two</pre></td><td></td><td></td></tr>
<tr><td class="line-num"></td><td></td><td class="added"><pre>five</pre></td><td class="line-num">2</td></tr>
<tr><td class="line-num">3</td><td><pre>three</pre></td><td><pre>three</pre></td><td class="line-num">3</td></tr>
<tr><td class="line-num">4</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">4</td></tr>
`,
},
{
`Beethoven
Bach
Mozart
Chopin
`,
`Beethoven
Bach
Brahms
Chopin
Liszt
Wagner
`,
[]DiffRecord{
{"Beethoven", Common},
{"Bach", Common},
{"Mozart", LeftOnly},
{"Brahms", RightOnly},
{"Chopin", Common},
{"Liszt", RightOnly},
{"Wagner", RightOnly},
{"", Common},
},
`<tr><td class="line-num">1</td><td><pre>Beethoven</pre></td><td><pre>Beethoven</pre></td><td class="line-num">1</td></tr>
<tr><td class="line-num">2</td><td><pre>Bach</pre></td><td><pre>Bach</pre></td><td class="line-num">2</td></tr>
<tr><td class="line-num">3</td><td class="deleted"><pre>Mozart</pre></td><td></td><td></td></tr>
<tr><td class="line-num"></td><td></td><td class="added"><pre>Brahms</pre></td><td class="line-num">3</td></tr>
<tr><td class="line-num">4</td><td><pre>Chopin</pre></td><td><pre>Chopin</pre></td><td class="line-num">4</td></tr>
<tr><td class="line-num"></td><td></td><td class="added"><pre>Liszt</pre></td><td class="line-num">5</td></tr>
<tr><td class="line-num"></td><td></td><td class="added"><pre>Wagner</pre></td><td class="line-num">6</td></tr>
<tr><td class="line-num">5</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">7</td></tr>
`,
},
{
`adagio
vivace
staccato legato
presto
lento
`,
`adagio adagio
staccato
staccato legato
staccato
legato
allegro
`,
[]DiffRecord{
{"adagio", LeftOnly},
{"vivace", LeftOnly},
{"adagio adagio", RightOnly},
{"staccato", RightOnly},
{"staccato legato", Common},
{"presto", LeftOnly},
{"lento", LeftOnly},
{"staccato", RightOnly},