<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 repr_test

import (
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestReprTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func makeLegalEntry() *fs.DirectoryEntry {
	entry := new(fs.DirectoryEntry)
	entry.Type = fs.TypeDirectory
	return entry
}

type MarshalTest struct {
}

func init() { RegisterTestSuite(&MarshalTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *MarshalTest) NoEntries() {
	// Input
	in := []*fs.DirectoryEntry{}

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	ExpectThat(out, ElementsAre())
}

func (t *MarshalTest) UnknownType() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[1].Type = 17

	// Marshal
	_, err := repr.Marshal(in)

	ExpectThat(err, Error(HasSubstr("EntryType")))
	ExpectThat(err, Error(HasSubstr("17")))
}

func (t *MarshalTest) PreservesTypes() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Type = fs.TypeFile
	in[1].Type = fs.TypeDirectory
	in[2].Type = fs.TypeSymlink

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any(), Any()))

	ExpectEq(in[0].Type, out[0].Type)
	ExpectEq(in[1].Type, out[1].Type)
	ExpectEq(in[2].Type, out[2].Type)
}

func (t *MarshalTest) PreservesNames() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Name = "taco"
	in[1].Name = "burrito"

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Name, out[0].Name)
	ExpectEq(in[1].Name, out[1].Name)
}

func (t *MarshalTest) PreservesPermissions() {
	ExpectEq("TODO", "")
}

func (t *MarshalTest) UnrepresentableModTime() {
	ExpectEq("TODO", "")
}

func (t *MarshalTest) PreservesModTimes() {
	ExpectEq("TODO", "")
}

func (t *MarshalTest) CopesWithLocationsInModTimes() {
	ExpectEq("TODO", "")
}

func (t *MarshalTest) PreservesScores() {
	ExpectEq("TODO", "")
}
<commit_msg>MarshalTest.PreservesPermissions<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 repr_test

import (
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestReprTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func makeLegalEntry() *fs.DirectoryEntry {
	entry := new(fs.DirectoryEntry)
	entry.Type = fs.TypeDirectory
	return entry
}

type MarshalTest struct {
}

func init() { RegisterTestSuite(&MarshalTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *MarshalTest) NoEntries() {
	// Input
	in := []*fs.DirectoryEntry{}

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	ExpectThat(out, ElementsAre())
}

func (t *MarshalTest) UnknownType() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[1].Type = 17

	// Marshal
	_, err := repr.Marshal(in)

	ExpectThat(err, Error(HasSubstr("EntryType")))
	ExpectThat(err, Error(HasSubstr("17")))
}

func (t *MarshalTest) PreservesTypes() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Type = fs.TypeFile
	in[1].Type = fs.TypeDirectory
	in[2].Type = fs.TypeSymlink

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any(), Any()))

	ExpectEq(in[0].Type, out[0].Type)
	ExpectEq(in[1].Type, out[1].Type)
	ExpectEq(in[2].Type, out[2].Type)
}

func (t *MarshalTest) PreservesNames() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Name = "taco"
	in[1].Name = "burrito"

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Name, out[0].Name)
	ExpectEq(in[1].Name, out[1].Name)
}

func (t *MarshalTest) PreservesPermissions() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Permissions = 0644
	in[1].Permissions = 0755

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Permissions, out[0].Permissions)
	ExpectEq(in[1].Permissions, out[1].Permissions)
}

func (t *MarshalTest) UnrepresentableModTime() {
	ExpectEq("TODO", "")
}

func (t *MarshalTest) PreservesModTimes() {
	ExpectEq("TODO", "")
}

func (t *MarshalTest) CopesWithLocationsInModTimes() {
	ExpectEq("TODO", "")
}

func (t *MarshalTest) PreservesScores() {
	ExpectEq("TODO", "")
}
<|endoftext|>


<commit_before>// +build windows

// Package userdir provides functions to get user directories
package userdir

import (
	"strings"
	"syscall"
	"unsafe"
)

// GetDataHome returns the user data directory.
func GetDataHome() string {
	return getRoamingAppDataDir()
}

// GetConfigHome returns the user config directory.
func GetConfigHome() string {
	return getRoamingAppDataDir()
}

type guid struct {
	data1 uint32
	data2 uint16
	data3 uint16
	data4 [8]byte
}

var (
	modshell32               = syscall.NewLazyDLL("shell32.dll")
	modole32                 = syscall.NewLazyDLL("ole32.dll")
	procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath")
	procCoTaskMemFree        = modole32.NewProc("CoTaskMemFree")

	roamingAppData = guid{
		0x3EB685DB,
		0x65F9,
		0x4CF6,
		[8]byte{0xA0, 0x3A, 0xE3, 0xEF, 0x65, 0x72, 0x9F, 0x3D},
	}
)

func coTaskMemFree(ptr uintptr) {
	procCoTaskMemFree.Call(ptr)
}

func getRoamingAppDataDir() string {
	dwFlags := uint32(0)
	var pwstr uintptr

	// NOTE(vincent): ignore the returned HRESULT, because, according to https://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx
	//  - the E_FAIL error can't be returned since the rfid we pass is static and well-defined.
	//  - the E_INVALIDARG error, as far as I know, can't be returned either since Roaming/AppData is always there.
	_, _, _ = procSHGetKnownFolderPath.Call(
		uintptr(unsafe.Pointer(&roamingAppData)),
		uintptr(dwFlags),
		uintptr(unsafe.Pointer(nil)),
		uintptr(unsafe.Pointer(&pwstr)),
	)
	defer coTaskMemFree(pwstr)

	return normalizeWindowsPath(utf16PtrToString(pwstr))
}

func normalizeWindowsPath(s string) string {
	return strings.Replace(s, "\\", "/", -1)
}

func utf16PtrToString(str uintptr) string {
	// TODO(vincent): see if we can do anything about go vet complaining
	ptr := unsafe.Pointer(str)
	return syscall.UTF16ToString((*[1 << 16]uint16)(ptr)[:])
}
<commit_msg>there's already a GUID type in syscall on WIndows<commit_after>// +build windows

// Package userdir provides functions to get user directories
package userdir

import (
	"strings"
	"syscall"
	"unsafe"
)

// GetDataHome returns the user data directory.
func GetDataHome() string {
	return getRoamingAppDataDir()
}

// GetConfigHome returns the user config directory.
func GetConfigHome() string {
	return getRoamingAppDataDir()
}

var (
	modshell32               = syscall.NewLazyDLL("shell32.dll")
	modole32                 = syscall.NewLazyDLL("ole32.dll")
	procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath")
	procCoTaskMemFree        = modole32.NewProc("CoTaskMemFree")

	roamingAppData = syscall.GUID{
		0x3EB685DB,
		0x65F9,
		0x4CF6,
		[8]byte{0xA0, 0x3A, 0xE3, 0xEF, 0x65, 0x72, 0x9F, 0x3D},
	}
)

func coTaskMemFree(ptr uintptr) {
	procCoTaskMemFree.Call(ptr)
}

func getRoamingAppDataDir() string {
	dwFlags := uint32(0)
	var pwstr uintptr

	// NOTE(vincent): ignore the returned HRESULT, because, according to https://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx
	//  - the E_FAIL error can't be returned since the rfid we pass is static and well-defined.
	//  - the E_INVALIDARG error, as far as I know, can't be returned either since Roaming/AppData is always there.
	_, _, _ = procSHGetKnownFolderPath.Call(
		uintptr(unsafe.Pointer(&roamingAppData)),
		uintptr(dwFlags),
		uintptr(unsafe.Pointer(nil)),
		uintptr(unsafe.Pointer(&pwstr)),
	)
	defer coTaskMemFree(pwstr)

	return normalizeWindowsPath(utf16PtrToString(pwstr))
}

func normalizeWindowsPath(s string) string {
	return strings.Replace(s, "\\", "/", -1)
}

func utf16PtrToString(str uintptr) string {
	// TODO(vincent): see if we can do anything about go vet complaining
	ptr := unsafe.Pointer(str)
	return syscall.UTF16ToString((*[1 << 16]uint16)(ptr)[:])
}
<|endoftext|>


<commit_before>/* Copyright 2018 The Bazel Authors. All rights reserved.

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 testtools

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// FileSpec specifies the content of a test file.
type FileSpec struct {
	// Path is a slash-separated path relative to the test directory. If Path
	// ends with a slash, it indicates a directory should be created
	// instead of a file.
	Path string

	// Symlink is a slash-separated path relative to the test directory. If set,
	// it indicates a symbolic link should be created with this path instead of a
	// file.
	Symlink string

	// Content is the content of the test file.
	Content string
}

// CreateFiles creates a directory of test files. This is a more compact
// alternative to testdata directories. CreateFiles returns a canonical path
// to the directory and a function to call to clean up the directory
// after the test.
func CreateFiles(t *testing.T, files []FileSpec) (dir string, cleanup func()) {
	dir, err := ioutil.TempDir(os.Getenv("TEST_TEMPDIR"), "gazelle_test")
	if err != nil {
		t.Fatal(err)
	}
	dir, err = filepath.EvalSymlinks(dir)
	if err != nil {
		t.Fatal(err)
	}

	for _, f := range files {
		path := filepath.Join(dir, filepath.FromSlash(f.Path))
		if strings.HasSuffix(f.Path, "/") {
			if err := os.MkdirAll(path, 0700); err != nil {
				os.RemoveAll(dir)
				t.Fatal(err)
			}
			continue
		}
		if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
			os.RemoveAll(dir)
			t.Fatal(err)
		}
		if f.Symlink != "" {
			if err := os.Symlink(f.Symlink, path); err != nil {
				t.Fatal(err)
			}
			continue
		}
		if err := ioutil.WriteFile(path, []byte(f.Content), 0600); err != nil {
			os.RemoveAll(dir)
			t.Fatal(err)
		}
	}

	return dir, func() { os.RemoveAll(dir) }
}

// CheckFiles checks that files in "dir" exist and have the content specified
// in "files". Files not listed in "files" are not tested, so extra files
// are allowed.
func CheckFiles(t *testing.T, dir string, files []FileSpec) {
	for _, f := range files {
		path := filepath.Join(dir, f.Path)
		if strings.HasSuffix(f.Path, "/") {
			if st, err := os.Stat(path); err != nil {
				t.Errorf("could not stat %s: %v", f.Path, err)
			} else if !st.IsDir() {
				t.Errorf("not a directory: %s", f.Path)
			}
		} else {
			want := strings.TrimSpace(f.Content)
			gotBytes, err := ioutil.ReadFile(filepath.Join(dir, f.Path))
			if err != nil {
				t.Errorf("could not read %s: %v", f.Path, err)
				continue
			}
			got := strings.TrimSpace(string(gotBytes))
			if got != want {
				t.Errorf("%s: got:\n%s\nwant:\n%s", f.Path, gotBytes, f.Content)
			}
		}
	}
}
<commit_msg>Add t.Helper() to all the testtools helper methods (#451)<commit_after>/* Copyright 2018 The Bazel Authors. All rights reserved.

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 testtools

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// FileSpec specifies the content of a test file.
type FileSpec struct {
	// Path is a slash-separated path relative to the test directory. If Path
	// ends with a slash, it indicates a directory should be created
	// instead of a file.
	Path string

	// Symlink is a slash-separated path relative to the test directory. If set,
	// it indicates a symbolic link should be created with this path instead of a
	// file.
	Symlink string

	// Content is the content of the test file.
	Content string
}

// CreateFiles creates a directory of test files. This is a more compact
// alternative to testdata directories. CreateFiles returns a canonical path
// to the directory and a function to call to clean up the directory
// after the test.
func CreateFiles(t *testing.T, files []FileSpec) (dir string, cleanup func()) {
	t.Helper()
	dir, err := ioutil.TempDir(os.Getenv("TEST_TEMPDIR"), "gazelle_test")
	if err != nil {
		t.Fatal(err)
	}
	dir, err = filepath.EvalSymlinks(dir)
	if err != nil {
		t.Fatal(err)
	}

	for _, f := range files {
		path := filepath.Join(dir, filepath.FromSlash(f.Path))
		if strings.HasSuffix(f.Path, "/") {
			if err := os.MkdirAll(path, 0700); err != nil {
				os.RemoveAll(dir)
				t.Fatal(err)
			}
			continue
		}
		if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
			os.RemoveAll(dir)
			t.Fatal(err)
		}
		if f.Symlink != "" {
			if err := os.Symlink(f.Symlink, path); err != nil {
				t.Fatal(err)
			}
			continue
		}
		if err := ioutil.WriteFile(path, []byte(f.Content), 0600); err != nil {
			os.RemoveAll(dir)
			t.Fatal(err)
		}
	}

	return dir, func() { os.RemoveAll(dir) }
}

// CheckFiles checks that files in "dir" exist and have the content specified
// in "files". Files not listed in "files" are not tested, so extra files
// are allowed.
func CheckFiles(t *testing.T, dir string, files []FileSpec) {
	t.Helper()
	for _, f := range files {
		path := filepath.Join(dir, f.Path)
		if strings.HasSuffix(f.Path, "/") {
			if st, err := os.Stat(path); err != nil {
				t.Errorf("could not stat %s: %v", f.Path, err)
			} else if !st.IsDir() {
				t.Errorf("not a directory: %s", f.Path)
			}
		} else {
			want := strings.TrimSpace(f.Content)
			gotBytes, err := ioutil.ReadFile(filepath.Join(dir, f.Path))
			if err != nil {
				t.Errorf("could not read %s: %v", f.Path, err)
				continue
			}
			got := strings.TrimSpace(string(gotBytes))
			if got != want {
				t.Errorf("%s: got:\n%s\nwant:\n%s", f.Path, gotBytes, f.Content)
			}
		}
	}
}
<|endoftext|>


<commit_before>package text

import (
	"testing"
)

func TestWord_Match(t *testing.T) {
	cases := []struct {
		s   string
		q   word
		exp int
	}{
		{
			s:   "foo",
			q:   Word("foo"),
			exp: 0,
		},
		{
			s:   "foo bar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo barbaz",
			q:   Word("bar"),
			exp: -1,
		},
		{
			s:   "foobar baz",
			q:   Word("bar"),
			exp: -1,
		},
		{
			s:   "foo bar",
			q:   Word("FOO"),
			exp: -1,
		},
		{
			s:   "FOO BAR",
			q:   Word("foo"),
			exp: -1,
		},
		{
			s:   "foo\tbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\nbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\vbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\fbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\rbar",
			q:   Word("bar"),
			exp: 4,
		},
	}

	for _, c := range cases {
		act := c.q.Match(c.s)

		if act != c.exp {
			t.Errorf("Expected Word(%q).Match(%q) to return %v, got %v", c.q.W, c.s, c.exp, act)
		}
	}
}

// BenchmarkWord_MatchNotExist6_587 benchmarks a single Word query of length
// 6 against a search text of length 587, where the sought string is at the
// very end of the search text.
//
// This benchmark gives a good indication of the average performance of an
// unsuccessful search.
func BenchmarkWord_MatchNotExist6_587(b *testing.B) {
	w := Word("foobar")

	txt := `Lorem ipsum dolor sit amet, an cum vero soleat concludaturque, te purto vero reprimique vis.
	Ignota mediocritatem ut sea. Cetero deserunt pericula te vel. Omnis legendos no per.
	Sale illum pertinax no sed, est posse putent minimum no. Pri et vitae mentitum eligendi,
	no ius reque fugit libris, eos ad quaeque pericula mediocrem. Habemus corpora an mea,
	inermis partiendo per et, at nemore dolorem iudicabit eos. At est mucius docendi. Sed et nisl facilisi.
	Idque suavitate argumentum eu eam, vis putant insolens dissentiunt id. Dictas labitur in mei, duo omnium assentior scripserit cu omnium`

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		w.Match(txt)
	}
}

// BenchmarkWord_MatchPartials5_587 benchmarks a single Word query of length
// 6 against a search text of length 587 with partials of length 5.
//
// This benchmark gives a good indication of the worst case performance
// of an unsuccessful search.
func BenchmarkWord_MatchPartials5_587(b *testing.B) {
	w := Word("foobar")

	txt := `fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba`

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		w.Match(txt)
	}
}

// BenchmarkWord_MatchExist6_587 benchmarks a single Word query of length
// 6 against a search text of length 587, where the sought string is at the
// very end of the search text.
func BenchmarkWord_MatchExist6_587(b *testing.B) {
	w := Word("foobar")

	txt := `Lorem ipsum dolor sit amet, an cum vero soleat concludaturque, te purto vero reprimique vis.
	Ignota mediocritatem ut sea. Cetero deserunt pericula te vel. Omnis legendos no per.
	Sale illum pertinax no sed, est posse putent minimum no. Pri et vitae mentitum eligendi,
	no ius reque fugit libris, eos ad quaeque pericula mediocrem. Habemus corpora an mea,
	inermis partiendo per et, at nemore dolorem iudicabit eos. At est mucius docendi. Sed et nisl facilisi.
	Idque suavitate argumentum eu eam, vis putant insolens dissentiunt id. Dictas labitur in mei, duo omnium assentior scripserit cu foobar`

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		w.Match(txt)
	}
}
<commit_msg>Correct comment<commit_after>package text

import (
	"testing"
)

func TestWord_Match(t *testing.T) {
	cases := []struct {
		s   string
		q   word
		exp int
	}{
		{
			s:   "foo",
			q:   Word("foo"),
			exp: 0,
		},
		{
			s:   "foo bar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo barbaz",
			q:   Word("bar"),
			exp: -1,
		},
		{
			s:   "foobar baz",
			q:   Word("bar"),
			exp: -1,
		},
		{
			s:   "foo bar",
			q:   Word("FOO"),
			exp: -1,
		},
		{
			s:   "FOO BAR",
			q:   Word("foo"),
			exp: -1,
		},
		{
			s:   "foo\tbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\nbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\vbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\fbar",
			q:   Word("bar"),
			exp: 4,
		},
		{
			s:   "foo\rbar",
			q:   Word("bar"),
			exp: 4,
		},
	}

	for _, c := range cases {
		act := c.q.Match(c.s)

		if act != c.exp {
			t.Errorf("Expected Word(%q).Match(%q) to return %v, got %v", c.q.W, c.s, c.exp, act)
		}
	}
}

// BenchmarkWord_MatchNotExist6_587 benchmarks a single Word query of length
// 6 against a search text of length 587, where the sought string does not
// exist in the search text.
//
// This benchmark gives a good indication of the average performance of an
// unsuccessful search.
func BenchmarkWord_MatchNotExist6_587(b *testing.B) {
	w := Word("foobar")

	txt := `Lorem ipsum dolor sit amet, an cum vero soleat concludaturque, te purto vero reprimique vis.
	Ignota mediocritatem ut sea. Cetero deserunt pericula te vel. Omnis legendos no per.
	Sale illum pertinax no sed, est posse putent minimum no. Pri et vitae mentitum eligendi,
	no ius reque fugit libris, eos ad quaeque pericula mediocrem. Habemus corpora an mea,
	inermis partiendo per et, at nemore dolorem iudicabit eos. At est mucius docendi. Sed et nisl facilisi.
	Idque suavitate argumentum eu eam, vis putant insolens dissentiunt id. Dictas labitur in mei, duo omnium assentior scripserit cu omnium`

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		w.Match(txt)
	}
}

// BenchmarkWord_MatchPartials5_587 benchmarks a single Word query of length
// 6 against a search text of length 587 with partials of length 5.
//
// This benchmark gives a good indication of the worst case performance
// of an unsuccessful search.
func BenchmarkWord_MatchPartials5_587(b *testing.B) {
	w := Word("foobar")

	txt := `fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba fooba fooba
		fooba fooba fooba fooba fooba fooba fooba fooba`

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		w.Match(txt)
	}
}

// BenchmarkWord_MatchExist6_587 benchmarks a single Word query of length
// 6 against a search text of length 587, where the sought string is at the
// very end of the search text.
func BenchmarkWord_MatchExist6_587(b *testing.B) {
	w := Word("foobar")

	txt := `Lorem ipsum dolor sit amet, an cum vero soleat concludaturque, te purto vero reprimique vis.
	Ignota mediocritatem ut sea. Cetero deserunt pericula te vel. Omnis legendos no per.
	Sale illum pertinax no sed, est posse putent minimum no. Pri et vitae mentitum eligendi,
	no ius reque fugit libris, eos ad quaeque pericula mediocrem. Habemus corpora an mea,
	inermis partiendo per et, at nemore dolorem iudicabit eos. At est mucius docendi. Sed et nisl facilisi.
	Idque suavitate argumentum eu eam, vis putant insolens dissentiunt id. Dictas labitur in mei, duo omnium assentior scripserit cu foobar`

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		w.Match(txt)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build !js,!windows

package driver

import (
	"fmt"
	"io"
	"runtime"

	"github.com/hajimehoshi/go-openal/openal"
)

// As x/mobile/exp/audio/al is broken on Mac OS X (https://github.com/golang/go/issues/15075),
// let's use github.com/hajimehoshi/go-openal instead.

const (
	maxBufferNum = 8
)

type Player struct {
	alDevice   *openal.Device
	alSource   openal.Source
	alBuffers  []openal.Buffer
	source     io.Reader
	sampleRate int
	isClosed   bool
	alFormat   openal.Format
}

func alFormat(channelNum, bytesPerSample int) openal.Format {
	switch {
	case channelNum == 1 && bytesPerSample == 1:
		return openal.FormatMono8
	case channelNum == 1 && bytesPerSample == 2:
		return openal.FormatMono16
	case channelNum == 2 && bytesPerSample == 1:
		return openal.FormatStereo8
	case channelNum == 2 && bytesPerSample == 2:
		return openal.FormatStereo16
	}
	panic(fmt.Sprintf("driver: invalid channel num (%d) or bytes per sample (%d)", channelNum, bytesPerSample))
}

func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) {
	d := openal.OpenDevice("")
	if d == nil {
		return nil, fmt.Errorf("driver: OpenDevice must not return nil")
	}
	c := d.CreateContext()
	if c == nil {
		return nil, fmt.Errorf("driver: CreateContext must not return nil")
	}
	// Don't check openal.Err until making the current context is done.
	// Linux might fail this check even though it succeeds (#204).
	c.Activate()
	if err := openal.Err(); err != nil {
		return nil, fmt.Errorf("driver: Activate: %v", err)
	}
	s := openal.NewSource()
	if err := openal.Err(); err != nil {
		return nil, fmt.Errorf("driver: NewSource: %v", err)
	}
	p := &Player{
		alDevice:   d,
		alSource:   s,
		alBuffers:  []openal.Buffer{},
		source:     src,
		sampleRate: sampleRate,
		alFormat:   alFormat(channelNum, bytesPerSample),
	}
	runtime.SetFinalizer(p, (*Player).Close)

	bs := openal.NewBuffers(maxBufferNum)
	emptyBytes := make([]byte, bufferSize)
	for _, b := range bs {
		// Note that the third argument of only the first buffer is used.
		b.SetData(p.alFormat, emptyBytes, int32(p.sampleRate))
		p.alSource.QueueBuffer(b)
	}
	p.alSource.Play()
	return p, nil
}

const (
	bufferSize = 1024
)

var (
	tmpBuffer    = make([]byte, bufferSize)
	tmpAlBuffers = make([]openal.Buffer, maxBufferNum)
)

func (p *Player) Proceed() error {
	if err := openal.Err(); err != nil {
		return fmt.Errorf("driver: starting Proceed: %v", err)
	}
	processedNum := p.alSource.BuffersProcessed()
	if 0 < processedNum {
		bufs := tmpAlBuffers[:processedNum]
		p.alSource.UnqueueBuffers(bufs)
		if err := openal.Err(); err != nil {
			return fmt.Errorf("driver: UnqueueBuffers: %v", err)
		}
		p.alBuffers = append(p.alBuffers, bufs...)
	}

	if 0 < len(p.alBuffers) {
		n, err := p.source.Read(tmpBuffer)
		if 0 < n {
			buf := p.alBuffers[0]
			p.alBuffers = p.alBuffers[1:]
			buf.SetData(p.alFormat, tmpBuffer[:n], int32(p.sampleRate))
			p.alSource.QueueBuffer(buf)
			if err := openal.Err(); err != nil {
				return fmt.Errorf("driver: QueueBuffer: %v", err)
			}
		}
		if err != nil {
			return err
		}
	}

	if p.alSource.State() == openal.Stopped || p.alSource.State() == openal.Initial {
		p.alSource.Rewind()
		p.alSource.Play()
		if err := openal.Err(); err != nil {
			return fmt.Errorf("driver: Rwind or Play: %v", err)
		}
	}

	return nil
}

func (p *Player) Close() error {
	if err := openal.Err(); err != nil {
		return fmt.Errorf("driver: starting Close: %v", err)
	}
	if p.isClosed {
		return nil
	}
	var bs []openal.Buffer
	p.alSource.Rewind()
	p.alSource.Play()
	if n := p.alSource.BuffersQueued(); 0 < n {
		bs = make([]openal.Buffer, n)
		p.alSource.UnqueueBuffers(bs)
		p.alBuffers = append(p.alBuffers, bs...)
	}
	p.alDevice.CloseDevice()
	p.isClosed = true
	if err := openal.Err(); err != nil {
		return fmt.Errorf("driver: CloseDevice: %v", err)
	}
	runtime.SetFinalizer(p, nil)
	return nil
}
<commit_msg>audio: Misspelling<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build !js,!windows

package driver

import (
	"fmt"
	"io"
	"runtime"

	"github.com/hajimehoshi/go-openal/openal"
)

// As x/mobile/exp/audio/al is broken on Mac OS X (https://github.com/golang/go/issues/15075),
// let's use github.com/hajimehoshi/go-openal instead.

const (
	maxBufferNum = 8
)

type Player struct {
	alDevice   *openal.Device
	alSource   openal.Source
	alBuffers  []openal.Buffer
	source     io.Reader
	sampleRate int
	isClosed   bool
	alFormat   openal.Format
}

func alFormat(channelNum, bytesPerSample int) openal.Format {
	switch {
	case channelNum == 1 && bytesPerSample == 1:
		return openal.FormatMono8
	case channelNum == 1 && bytesPerSample == 2:
		return openal.FormatMono16
	case channelNum == 2 && bytesPerSample == 1:
		return openal.FormatStereo8
	case channelNum == 2 && bytesPerSample == 2:
		return openal.FormatStereo16
	}
	panic(fmt.Sprintf("driver: invalid channel num (%d) or bytes per sample (%d)", channelNum, bytesPerSample))
}

func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) {
	d := openal.OpenDevice("")
	if d == nil {
		return nil, fmt.Errorf("driver: OpenDevice must not return nil")
	}
	c := d.CreateContext()
	if c == nil {
		return nil, fmt.Errorf("driver: CreateContext must not return nil")
	}
	// Don't check openal.Err until making the current context is done.
	// Linux might fail this check even though it succeeds (#204).
	c.Activate()
	if err := openal.Err(); err != nil {
		return nil, fmt.Errorf("driver: Activate: %v", err)
	}
	s := openal.NewSource()
	if err := openal.Err(); err != nil {
		return nil, fmt.Errorf("driver: NewSource: %v", err)
	}
	p := &Player{
		alDevice:   d,
		alSource:   s,
		alBuffers:  []openal.Buffer{},
		source:     src,
		sampleRate: sampleRate,
		alFormat:   alFormat(channelNum, bytesPerSample),
	}
	runtime.SetFinalizer(p, (*Player).Close)

	bs := openal.NewBuffers(maxBufferNum)
	emptyBytes := make([]byte, bufferSize)
	for _, b := range bs {
		// Note that the third argument of only the first buffer is used.
		b.SetData(p.alFormat, emptyBytes, int32(p.sampleRate))
		p.alSource.QueueBuffer(b)
	}
	p.alSource.Play()
	return p, nil
}

const (
	bufferSize = 1024
)

var (
	tmpBuffer    = make([]byte, bufferSize)
	tmpAlBuffers = make([]openal.Buffer, maxBufferNum)
)

func (p *Player) Proceed() error {
	if err := openal.Err(); err != nil {
		return fmt.Errorf("driver: starting Proceed: %v", err)
	}
	processedNum := p.alSource.BuffersProcessed()
	if 0 < processedNum {
		bufs := tmpAlBuffers[:processedNum]
		p.alSource.UnqueueBuffers(bufs)
		if err := openal.Err(); err != nil {
			return fmt.Errorf("driver: UnqueueBuffers: %v", err)
		}
		p.alBuffers = append(p.alBuffers, bufs...)
	}

	if 0 < len(p.alBuffers) {
		n, err := p.source.Read(tmpBuffer)
		if 0 < n {
			buf := p.alBuffers[0]
			p.alBuffers = p.alBuffers[1:]
			buf.SetData(p.alFormat, tmpBuffer[:n], int32(p.sampleRate))
			p.alSource.QueueBuffer(buf)
			if err := openal.Err(); err != nil {
				return fmt.Errorf("driver: QueueBuffer: %v", err)
			}
		}
		if err != nil {
			return err
		}
	}

	if p.alSource.State() == openal.Stopped || p.alSource.State() == openal.Initial {
		p.alSource.Rewind()
		p.alSource.Play()
		if err := openal.Err(); err != nil {
			return fmt.Errorf("driver: Rewind or Play: %v", err)
		}
	}

	return nil
}

func (p *Player) Close() error {
	if err := openal.Err(); err != nil {
		return fmt.Errorf("driver: starting Close: %v", err)
	}
	if p.isClosed {
		return nil
	}
	var bs []openal.Buffer
	p.alSource.Rewind()
	p.alSource.Play()
	if n := p.alSource.BuffersQueued(); 0 < n {
		bs = make([]openal.Buffer, n)
		p.alSource.UnqueueBuffers(bs)
		p.alBuffers = append(p.alBuffers, bs...)
	}
	p.alDevice.CloseDevice()
	p.isClosed = true
	if err := openal.Err(); err != nil {
		return fmt.Errorf("driver: CloseDevice: %v", err)
	}
	runtime.SetFinalizer(p, nil)
	return nil
}
<|endoftext|>


<commit_before>package types

import (
	"fmt"
	"reflect"
)

// ToString transforms the given value into
// a string. If the value is a nil pointer
// or a nil interface, it returns the empty
// string.
func ToString(val interface{}) string {
	if val == nil {
		return ""
	}
	v := reflect.ValueOf(val)
	if k := v.Kind(); k == reflect.Ptr || k == reflect.Interface {
		if v.IsNil() {
			return ""
		}
	}
	// Can't do this before the IsNil test, because Go has
	// this weird concept of non-nil interface which points
	// to a nil pointer, what a great idea!
	switch x := val.(type) {
	case string:
		return x
	case fmt.Stringer:
		return x.String()
	case error:
		return x.Error()
	}
	return fmt.Sprintf("%v", val)
}

// ToInt tries to convert its argument to an integer. It will convert
// bool, uint and its varities, floats and even strings if it can parse
// them.
func ToInt(val interface{}) (int, error) {
	iv := reflect.ValueOf(val)
	if !iv.IsValid() {
		return 0, fmt.Errorf("invalid value")
	}
	v := reflect.Indirect(iv)
	switch v.Kind() {
	case reflect.String:
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return int(v.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return int(v.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return int(v.Float()), nil
	}
	return 0, fmt.Errorf("can't convert %v to int", v.Type())
}

// Equal is a shortcut for reflect.DeepEqual.
func Equal(obj1, obj2 interface{}) bool {
	return reflect.DeepEqual(obj1, obj2)
}

// IsTrue returns whether the value is 'true', in the sense of not the zero of its type,
// and whether the value has a meaningful truth value. This function is a copy of the
// one found in text/template
func IsTrue(value interface{}) (truth, ok bool) {
	return IsTrueVal(reflect.ValueOf(value))
}

// IsTrueVal works like IsTrue, but accepts a reflect.Value rather
// than an interface{}.
func IsTrueVal(val reflect.Value) (truth, ok bool) {
	if !val.IsValid() {
		// Something like var x interface{}, never set. It's a form of nil.
		return false, true
	}
	switch val.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		truth = val.Len() > 0
	case reflect.Bool:
		truth = val.Bool()
	case reflect.Complex64, reflect.Complex128:
		truth = val.Complex() != 0
	case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
		truth = !val.IsNil()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		truth = val.Int() != 0
	case reflect.Float32, reflect.Float64:
		truth = val.Float() != 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		truth = val.Uint() != 0
	case reflect.Struct:
		truth = true // Struct values are always true.
	default:
		return
	}
	return truth, true
}

// IsInt returns true iff typ is any of the int types.
func IsInt(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Int || k == reflect.Int8 || k == reflect.Int16 || k == reflect.Int32 || k == reflect.Int64
}

// IsUint returns true iff typ is any of the uint types.
func IsUint(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Uint || k == reflect.Uint8 || k == reflect.Uint16 || k == reflect.Uint32 || k == reflect.Uint64
}

// IsFloat returns true iff typ is any of the float types.
func IsFloat(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Float32 || k == reflect.Float64
}
<commit_msg>Fix ToInt for strings<commit_after>package types

import (
	"fmt"
	"reflect"
	"strconv"
)

// ToString transforms the given value into
// a string. If the value is a nil pointer
// or a nil interface, it returns the empty
// string.
func ToString(val interface{}) string {
	if val == nil {
		return ""
	}
	v := reflect.ValueOf(val)
	if k := v.Kind(); k == reflect.Ptr || k == reflect.Interface {
		if v.IsNil() {
			return ""
		}
	}
	// Can't do this before the IsNil test, because Go has
	// this weird concept of non-nil interface which points
	// to a nil pointer, what a great idea!
	switch x := val.(type) {
	case string:
		return x
	case fmt.Stringer:
		return x.String()
	case error:
		return x.Error()
	}
	return fmt.Sprintf("%v", val)
}

// ToInt tries to convert its argument to an integer. It will convert
// bool, int, uint and its variants, floats and even strings if it can parse
// them.
func ToInt(val interface{}) (int, error) {
	iv := reflect.ValueOf(val)
	if !iv.IsValid() {
		return 0, fmt.Errorf("invalid value")
	}
	v := reflect.Indirect(iv)
	switch v.Kind() {
	case reflect.String:
		val, err := strconv.ParseInt(v.String(), 0, 64)
		return int(val), err
	case reflect.Bool:
		if v.Bool() {
			return 1, nil
		}
		return 0, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return int(v.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return int(v.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return int(v.Float()), nil
	}
	return 0, fmt.Errorf("can't convert %v to int", v.Type())
}

// Equal is a shortcut for reflect.DeepEqual.
func Equal(obj1, obj2 interface{}) bool {
	return reflect.DeepEqual(obj1, obj2)
}

// IsTrue returns whether the value is 'true', in the sense of not the zero of its type,
// and whether the value has a meaningful truth value. This function is a copy of the
// one found in text/template
func IsTrue(value interface{}) (truth, ok bool) {
	return IsTrueVal(reflect.ValueOf(value))
}

// IsTrueVal works like IsTrue, but accepts a reflect.Value rather
// than an interface{}.
func IsTrueVal(val reflect.Value) (truth, ok bool) {
	if !val.IsValid() {
		// Something like var x interface{}, never set. It's a form of nil.
		return false, true
	}
	switch val.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		truth = val.Len() > 0
	case reflect.Bool:
		truth = val.Bool()
	case reflect.Complex64, reflect.Complex128:
		truth = val.Complex() != 0
	case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
		truth = !val.IsNil()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		truth = val.Int() != 0
	case reflect.Float32, reflect.Float64:
		truth = val.Float() != 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		truth = val.Uint() != 0
	case reflect.Struct:
		truth = true // Struct values are always true.
	default:
		return
	}
	return truth, true
}

// IsInt returns true iff typ is any of the int types.
func IsInt(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Int || k == reflect.Int8 || k == reflect.Int16 || k == reflect.Int32 || k == reflect.Int64
}

// IsUint returns true iff typ is any of the uint types.
func IsUint(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Uint || k == reflect.Uint8 || k == reflect.Uint16 || k == reflect.Uint32 || k == reflect.Uint64
}

// IsFloat returns true iff typ is any of the float types.
func IsFloat(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Float32 || k == reflect.Float64
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

// -----------------------
// --- Constants
// -----------------------

const (
	hockeyAppDeployStatusKey     = "HOCKEYAPP_DEPLOY_STATUS"
	hockeyAppDeployStatusSuccess = "success"
	hockeyAppDeployStatusFailed  = "failed"
	hockeyAppDeployPublicURLKey  = "HOCKEYAPP_DEPLOY_PUBLIC_URL"
	hockeyAppDeployBuildURLKey   = "HOCKEYAPP_DEPLOY_BUILD_URL"
	hockeyAppDeployConfigURLKey  = "HOCKEYAPP_DEPLOY_CONFIG_URL"
)

// -----------------------
// --- Models
// -----------------------

// ResponseModel ...
type ResponseModel struct {
	ConfigURL string `json:"config_url"`
	PublicURL string `json:"public_url"`
	BuildURL  string `json:"build_url"`
}

// -----------------------
// --- Functions
// -----------------------

func logFail(format string, v ...interface{}) {
	if err := exportEnvironmentWithEnvman(hockeyAppDeployStatusKey, hockeyAppDeployStatusFailed); err != nil {
		logWarn("Failed to export %s, error: %s", hockeyAppDeployStatusKey, err)
	}

	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("\x1b[31;1m%s\x1b[0m\n", errorMsg)
	os.Exit(1)
}

func logWarn(format string, v ...interface{}) {
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("\x1b[33;1m%s\x1b[0m\n", errorMsg)
}

func logInfo(format string, v ...interface{}) {
	fmt.Println()
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("\x1b[34;1m%s\x1b[0m\n", errorMsg)
}

func logDetails(format string, v ...interface{}) {
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("  \x1b[97;1m%s\x1b[0m\n", errorMsg)
}

func logDone(format string, v ...interface{}) {
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("  \x1b[32;1m%s\x1b[0m\n", errorMsg)
}

func exportEnvironmentWithEnvman(keyStr, valueStr string) error {
	envman := exec.Command("envman", "add", "--key", keyStr)
	envman.Stdin = strings.NewReader(valueStr)
	envman.Stdout = os.Stdout
	envman.Stderr = os.Stderr
	return envman.Run()
}

func createRequest(url string, fields, files map[string]string) (*http.Request, error) {
	var b bytes.Buffer
	w := multipart.NewWriter(&b)

	// Add fields
	for key, value := range fields {
		if err := w.WriteField(key, value); err != nil {
			return nil, err
		}
	}

	// Add files
	for key, file := range files {
		f, err := os.Open(file)
		if err != nil {
			return nil, err
		}
		fw, err := w.CreateFormFile(key, file)
		if err != nil {
			return nil, err
		}
		if _, err = io.Copy(fw, f); err != nil {
			return nil, err
		}
	}

	w.Close()

	req, err := http.NewRequest("POST", url, &b)
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", w.FormDataContentType())

	return req, nil
}

// -----------------------
// --- Main
// -----------------------

func main() {
	//
	// Validate options
	ipaPath := ""
	if ipaPath = os.Getenv("ipa_path"); ipaPath == "" {
		logFail("No IPA found to deploy. Specified path was: %s", ipaPath)
	}

	dsymPath := ""
	if dsymPath = os.Getenv("dsym_path"); dsymPath == "" {
		logFail("DSYM file not found to deploy. Specified path was: %s. To generate debug symbols (dSYM) go to your Xcode Project Settings - `Build Settings - Debug Information Format` and set it to **DWARF with dSYM File**.", dsymPath)
	}

	apiToken := ""
	if apiToken = os.Getenv("api_token"); apiToken == "" {
		logFail("No App api_token provided as environment variable. Terminating...")
	}

	appID := os.Getenv("app_id")
	notes := os.Getenv("notes")
	notesType := os.Getenv("notes_type")
	notify := os.Getenv("notify")
	status := os.Getenv("status")
	mandatory := os.Getenv("mandatory")
	tags := os.Getenv("tags")
	commitSHA := os.Getenv("commit_sha")
	buildServerURL := os.Getenv("build_server_url")
	repositoryURL := os.Getenv("repository_url")

	logInfo("Configs:")
	logDetails("ipa_path: %s", ipaPath)
	logDetails("dsym_path: %s", dsymPath)
	logDetails("api_token: ***")
	logDetails("app_id: %s", appID)
	logDetails("notes: %s", notes)
	logDetails("notes_type: %s", notesType)
	logDetails("notify: %s", notify)
	logDetails("status: %s", status)
	logDetails("mandatory: %s", mandatory)
	logDetails("tags: %s", tags)
	logDetails("commit_sha: %s", commitSHA)
	logDetails("build_server_url: %s", buildServerURL)
	logDetails("repository_url: %s", repositoryURL)

	//
	// Create request
	logInfo("Performing request")

	requestURL := "https://rink.hockeyapp.net/api/2/apps/upload"
	if appID != "" {
		requestURL = fmt.Sprintf("https://rink.hockeyapp.net/api/2/apps/%s/app_versions/upload", appID)
	}

	fields := map[string]string{
		"notes":            notes,
		"notes_type":       notesType,
		"notify":           notify,
		"status":           status,
		"mandatory":        mandatory,
		"tags":             tags,
		"commit_sha":       commitSHA,
		"build_server_url": buildServerURL,
		"repository_url":   repositoryURL,
	}

	files := map[string]string{
		"ipa":  ipaPath,
		"dsym": dsymPath,
	}

	request, err := createRequest(requestURL, fields, files)
	if err != nil {
		logFail("Failed to create request, error: %#v", err)
	}
	request.Header.Add("X-HockeyAppToken", apiToken)

	client := http.Client{}
	response, requestErr := client.Do(request)

	defer response.Body.Close()
	contents, readErr := ioutil.ReadAll(response.Body)

	//
	// Process response

	// Error
	if requestErr != nil {
		if readErr != nil {
			logWarn("Failed to read response body, error: %#v", readErr)
		} else {
			logInfo("Response:")
			logDetails("status code: %d", response.StatusCode)
			logDetails("body: %s", string(contents))
		}
		logFail("Performing request failed, error: %#v", requestErr)
	}

	if response.StatusCode < 200 || response.StatusCode > 300 {
		if readErr != nil {
			logWarn("Failed to read response body, error: %#v", readErr)
		} else {
			logInfo("Response:")
			logDetails("status code: %d", response.StatusCode)
			logDetails("body: %s", string(contents))
		}
		logFail("Performing request failed, status code: %d", response.StatusCode)
	}

	// Success
	logDone("Request succed")

	logInfo("Response:")
	logDetails("status code: %d", response.StatusCode)
	logDetails("body: %s", contents)

	if readErr != nil {
		logFail("Failed to read response body, error: %#v", readErr)
	}

	var responseModel ResponseModel
	if err := json.Unmarshal([]byte(contents), &responseModel); err != nil {
		logFail("Failed to parse response body, error: %#v", err)
	}

	fmt.Println()
	if responseModel.PublicURL != "" {
		logDone("Public URL: %s", responseModel.PublicURL)
	}
	if responseModel.BuildURL != "" {
		logDone("Build (direct download) URL: %s", responseModel.BuildURL)
	}
	if responseModel.ConfigURL != "" {
		logDone("Config URL: %s", responseModel.ConfigURL)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployStatusKey, hockeyAppDeployStatusSuccess); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployStatusKey, err)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployPublicURLKey, responseModel.PublicURL); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployPublicURLKey, err)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployBuildURLKey, responseModel.BuildURL); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployBuildURLKey, err)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployConfigURLKey, responseModel.ConfigURL); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployConfigURLKey, err)
	}
}
<commit_msg>check if ipa and dsym path files exist<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

// -----------------------
// --- Constants
// -----------------------

const (
	hockeyAppDeployStatusKey     = "HOCKEYAPP_DEPLOY_STATUS"
	hockeyAppDeployStatusSuccess = "success"
	hockeyAppDeployStatusFailed  = "failed"
	hockeyAppDeployPublicURLKey  = "HOCKEYAPP_DEPLOY_PUBLIC_URL"
	hockeyAppDeployBuildURLKey   = "HOCKEYAPP_DEPLOY_BUILD_URL"
	hockeyAppDeployConfigURLKey  = "HOCKEYAPP_DEPLOY_CONFIG_URL"
)

// -----------------------
// --- Models
// -----------------------

// ResponseModel ...
type ResponseModel struct {
	ConfigURL string `json:"config_url"`
	PublicURL string `json:"public_url"`
	BuildURL  string `json:"build_url"`
}

// -----------------------
// --- Functions
// -----------------------

func logFail(format string, v ...interface{}) {
	if err := exportEnvironmentWithEnvman(hockeyAppDeployStatusKey, hockeyAppDeployStatusFailed); err != nil {
		logWarn("Failed to export %s, error: %s", hockeyAppDeployStatusKey, err)
	}

	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("\x1b[31;1m%s\x1b[0m\n", errorMsg)
	os.Exit(1)
}

func logWarn(format string, v ...interface{}) {
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("\x1b[33;1m%s\x1b[0m\n", errorMsg)
}

func logInfo(format string, v ...interface{}) {
	fmt.Println()
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("\x1b[34;1m%s\x1b[0m\n", errorMsg)
}

func logDetails(format string, v ...interface{}) {
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("  %s\n", errorMsg)
}

func logDone(format string, v ...interface{}) {
	errorMsg := fmt.Sprintf(format, v...)
	fmt.Printf("  \x1b[32;1m%s\x1b[0m\n", errorMsg)
}

func genericIsPathExists(pth string) (os.FileInfo, bool, error) {
	if pth == "" {
		return nil, false, errors.New("No path provided")
	}
	fileInf, err := os.Stat(pth)
	if err == nil {
		return fileInf, true, nil
	}
	if os.IsNotExist(err) {
		return nil, false, nil
	}
	return fileInf, false, err
}

// IsPathExists ...
func IsPathExists(pth string) (bool, error) {
	_, isExists, err := genericIsPathExists(pth)
	return isExists, err
}

func exportEnvironmentWithEnvman(keyStr, valueStr string) error {
	envman := exec.Command("envman", "add", "--key", keyStr)
	envman.Stdin = strings.NewReader(valueStr)
	envman.Stdout = os.Stdout
	envman.Stderr = os.Stderr
	return envman.Run()
}

func createRequest(url string, fields, files map[string]string) (*http.Request, error) {
	var b bytes.Buffer
	w := multipart.NewWriter(&b)

	// Add fields
	for key, value := range fields {
		if err := w.WriteField(key, value); err != nil {
			return nil, err
		}
	}

	// Add files
	for key, file := range files {
		f, err := os.Open(file)
		if err != nil {
			return nil, err
		}
		fw, err := w.CreateFormFile(key, file)
		if err != nil {
			return nil, err
		}
		if _, err = io.Copy(fw, f); err != nil {
			return nil, err
		}
	}

	w.Close()

	req, err := http.NewRequest("POST", url, &b)
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", w.FormDataContentType())

	return req, nil
}

// -----------------------
// --- Main
// -----------------------

func main() {
	//
	// Validate options
	ipaPath := ""
	if ipaPath = os.Getenv("ipa_path"); ipaPath == "" {
		logFail("Missing required input: ipa_path")
	}
	if exist, err := IsPathExists(ipaPath); err != nil {
		logFail("Failed to check if path (%s) exist, error: %#v", ipaPath, err)
	} else if !exist {
		logFail("No IPA found to deploy. Specified path was: %s", ipaPath)
	}

	dsymPath := ""
	if dsymPath = os.Getenv("dsym_path"); dsymPath == "" {
		logFail("Missing required input: dsym_path")
	}
	if exist, err := IsPathExists(dsymPath); err != nil {
		logFail("Failed to check if path (%s) exist, error: %#v", dsymPath, err)
	} else if !exist {
		logFail("DSYM file not found to deploy. Specified path was: %s. To generate debug symbols (dSYM) go to your Xcode Project Settings - `Build Settings - Debug Information Format` and set it to **DWARF with dSYM File**.", dsymPath)
	}

	apiToken := ""
	if apiToken = os.Getenv("api_token"); apiToken == "" {
		logFail("No App api_token provided as environment variable. Terminating...")
	}

	appID := os.Getenv("app_id")
	notes := os.Getenv("notes")
	notesType := os.Getenv("notes_type")
	notify := os.Getenv("notify")
	status := os.Getenv("status")
	mandatory := os.Getenv("mandatory")
	tags := os.Getenv("tags")
	commitSHA := os.Getenv("commit_sha")
	buildServerURL := os.Getenv("build_server_url")
	repositoryURL := os.Getenv("repository_url")

	logInfo("Configs:")
	logDetails("ipa_path: %s", ipaPath)
	logDetails("dsym_path: %s", dsymPath)
	logDetails("api_token: ***")
	logDetails("app_id: %s", appID)
	logDetails("notes: %s", notes)
	logDetails("notes_type: %s", notesType)
	logDetails("notify: %s", notify)
	logDetails("status: %s", status)
	logDetails("mandatory: %s", mandatory)
	logDetails("tags: %s", tags)
	logDetails("commit_sha: %s", commitSHA)
	logDetails("build_server_url: %s", buildServerURL)
	logDetails("repository_url: %s", repositoryURL)

	//
	// Create request
	logInfo("Performing request")

	requestURL := "https://rink.hockeyapp.net/api/2/apps/upload"
	if appID != "" {
		requestURL = fmt.Sprintf("https://rink.hockeyapp.net/api/2/apps/%s/app_versions/upload", appID)
	}

	fields := map[string]string{
		"notes":            notes,
		"notes_type":       notesType,
		"notify":           notify,
		"status":           status,
		"mandatory":        mandatory,
		"tags":             tags,
		"commit_sha":       commitSHA,
		"build_server_url": buildServerURL,
		"repository_url":   repositoryURL,
	}

	files := map[string]string{
		"ipa":  ipaPath,
		"dsym": dsymPath,
	}

	request, err := createRequest(requestURL, fields, files)
	if err != nil {
		logFail("Failed to create request, error: %#v", err)
	}
	request.Header.Add("X-HockeyAppToken", apiToken)

	client := http.Client{}
	response, requestErr := client.Do(request)

	defer response.Body.Close()
	contents, readErr := ioutil.ReadAll(response.Body)

	//
	// Process response

	// Error
	if requestErr != nil {
		if readErr != nil {
			logWarn("Failed to read response body, error: %#v", readErr)
		} else {
			logInfo("Response:")
			logDetails("status code: %d", response.StatusCode)
			logDetails("body: %s", string(contents))
		}
		logFail("Performing request failed, error: %#v", requestErr)
	}

	if response.StatusCode < 200 || response.StatusCode > 300 {
		if readErr != nil {
			logWarn("Failed to read response body, error: %#v", readErr)
		} else {
			logInfo("Response:")
			logDetails("status code: %d", response.StatusCode)
			logDetails("body: %s", string(contents))
		}
		logFail("Performing request failed, status code: %d", response.StatusCode)
	}

	// Success
	logDone("Request succed")

	logInfo("Response:")
	logDetails("status code: %d", response.StatusCode)
	logDetails("body: %s", contents)

	if readErr != nil {
		logFail("Failed to read response body, error: %#v", readErr)
	}

	var responseModel ResponseModel
	if err := json.Unmarshal([]byte(contents), &responseModel); err != nil {
		logFail("Failed to parse response body, error: %#v", err)
	}

	fmt.Println()
	if responseModel.PublicURL != "" {
		logDone("Public URL: %s", responseModel.PublicURL)
	}
	if responseModel.BuildURL != "" {
		logDone("Build (direct download) URL: %s", responseModel.BuildURL)
	}
	if responseModel.ConfigURL != "" {
		logDone("Config URL: %s", responseModel.ConfigURL)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployStatusKey, hockeyAppDeployStatusSuccess); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployStatusKey, err)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployPublicURLKey, responseModel.PublicURL); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployPublicURLKey, err)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployBuildURLKey, responseModel.BuildURL); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployBuildURLKey, err)
	}

	if err := exportEnvironmentWithEnvman(hockeyAppDeployConfigURLKey, responseModel.ConfigURL); err != nil {
		logFail("Failed to export %s, error: %#v", hockeyAppDeployConfigURLKey, err)
	}
}
<|endoftext|>


<commit_before>// generated by stringer -type=Quad -output=quadrant_string.go; DO NOT EDIT

package coord

import "fmt"

const _Quad_name = "NWQUAD_NEQUAD_SEQUAD_SW"

var _Quad_index = [...]uint8{0, 2, 9, 16, 23}

func (i Quad) String() string {
	if i < 0 || i+1 >= Quad(len(_Quad_index)) {
		return fmt.Sprintf("Quad(%d)", i)
	}
	return _Quad_name[_Quad_index[i]:_Quad_index[i+1]]
}
<commit_msg>[rpg2d/coord] update generated stringer for quadrant constants<commit_after>// generated by stringer -type=Quad -output=quadrant_string.go; DO NOT EDIT

package coord

import "fmt"

const _Quad_name = "NWNESESW"

var _Quad_index = [...]uint8{0, 2, 4, 6, 8}

func (i Quad) String() string {
	if i < 0 || i+1 >= Quad(len(_Quad_index)) {
		return fmt.Sprintf("Quad(%d)", i)
	}
	return _Quad_name[_Quad_index[i]:_Quad_index[i+1]]
}
<|endoftext|>


<commit_before>package daemon // import "github.com/docker/docker/daemon"

import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/strslice"
	"github.com/docker/docker/container"
	"github.com/docker/docker/daemon/network"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/image"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/signal"
	"github.com/docker/docker/pkg/system"
	"github.com/docker/docker/pkg/truncindex"
	"github.com/docker/docker/runconfig"
	volumemounts "github.com/docker/docker/volume/mounts"
	"github.com/docker/go-connections/nat"
	"github.com/opencontainers/selinux/go-selinux/label"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// GetContainer looks for a container using the provided information, which could be
// one of the following inputs from the caller:
//  - A full container ID, which will exact match a container in daemon's list
//  - A container name, which will only exact match via the GetByName() function
//  - A partial container ID prefix (e.g. short ID) of any length that is
//    unique enough to only return a single container object
//  If none of these searches succeed, an error is returned
func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, error) {
	if len(prefixOrName) == 0 {
		return nil, errors.WithStack(invalidIdentifier(prefixOrName))
	}

	if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil {
		// prefix is an exact match to a full container ID
		return containerByID, nil
	}

	// GetByName will match only an exact name provided; we ignore errors
	if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil {
		// prefix is an exact match to a full container Name
		return containerByName, nil
	}

	containerID, indexError := daemon.idIndex.Get(prefixOrName)
	if indexError != nil {
		// When truncindex defines an error type, use that instead
		if indexError == truncindex.ErrNotExist {
			return nil, containerNotFound(prefixOrName)
		}
		return nil, errdefs.System(indexError)
	}
	return daemon.containers.Get(containerID), nil
}

// checkContainer make sure the specified container validates the specified conditions
func (daemon *Daemon) checkContainer(container *container.Container, conditions ...func(*container.Container) error) error {
	for _, condition := range conditions {
		if err := condition(container); err != nil {
			return err
		}
	}
	return nil
}

// Exists returns a true if a container of the specified ID or name exists,
// false otherwise.
func (daemon *Daemon) Exists(id string) bool {
	c, _ := daemon.GetContainer(id)
	return c != nil
}

// IsPaused returns a bool indicating if the specified container is paused.
func (daemon *Daemon) IsPaused(id string) bool {
	c, _ := daemon.GetContainer(id)
	return c.State.IsPaused()
}

func (daemon *Daemon) containerRoot(id string) string {
	return filepath.Join(daemon.repository, id)
}

// Load reads the contents of a container from disk
// This is typically done at startup.
func (daemon *Daemon) load(id string) (*container.Container, error) {
	container := daemon.newBaseContainer(id)

	if err := container.FromDisk(); err != nil {
		return nil, err
	}
	if err := label.ReserveLabel(container.ProcessLabel); err != nil {
		return nil, err
	}

	if container.ID != id {
		return container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
	}

	return container, nil
}

// Register makes a container object usable by the daemon as <container.ID>
func (daemon *Daemon) Register(c *container.Container) error {
	// Attach to stdout and stderr
	if c.Config.OpenStdin {
		c.StreamConfig.NewInputPipes()
	} else {
		c.StreamConfig.NewNopInputPipe()
	}

	// once in the memory store it is visible to other goroutines
	// grab a Lock until it has been checkpointed to avoid races
	c.Lock()
	defer c.Unlock()

	daemon.containers.Add(c.ID, c)
	daemon.idIndex.Add(c.ID)
	return c.CheckpointTo(daemon.containersReplica)
}

func (daemon *Daemon) newContainer(name string, operatingSystem string, config *containertypes.Config, hostConfig *containertypes.HostConfig, imgID image.ID, managed bool) (*container.Container, error) {
	var (
		id             string
		err            error
		noExplicitName = name == ""
	)
	id, name, err = daemon.generateIDAndName(name)
	if err != nil {
		return nil, err
	}

	if hostConfig.NetworkMode.IsHost() {
		if config.Hostname == "" {
			config.Hostname, err = os.Hostname()
			if err != nil {
				return nil, errdefs.System(err)
			}
		}
	} else {
		daemon.generateHostname(id, config)
	}
	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)

	base := daemon.newBaseContainer(id)
	base.Created = time.Now().UTC()
	base.Managed = managed
	base.Path = entrypoint
	base.Args = args //FIXME: de-duplicate from config
	base.Config = config
	base.HostConfig = &containertypes.HostConfig{}
	base.ImageID = imgID
	base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName}
	base.Name = name
	base.Driver = daemon.imageService.GraphDriverForOS(operatingSystem)
	base.OS = operatingSystem
	return base, err
}

// GetByName returns a container given a name.
func (daemon *Daemon) GetByName(name string) (*container.Container, error) {
	if len(name) == 0 {
		return nil, fmt.Errorf("No container name supplied")
	}
	fullName := name
	if name[0] != '/' {
		fullName = "/" + name
	}
	id, err := daemon.containersReplica.Snapshot().GetID(fullName)
	if err != nil {
		return nil, fmt.Errorf("Could not find entity for %s", name)
	}
	e := daemon.containers.Get(id)
	if e == nil {
		return nil, fmt.Errorf("Could not find container for entity id %s", id)
	}
	return e, nil
}

// newBaseContainer creates a new container with its initial
// configuration based on the root storage from the daemon.
func (daemon *Daemon) newBaseContainer(id string) *container.Container {
	return container.NewBaseContainer(id, daemon.containerRoot(id))
}

func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) {
	if len(configEntrypoint) != 0 {
		return configEntrypoint[0], append(configEntrypoint[1:], configCmd...)
	}
	return configCmd[0], configCmd[1:]
}

func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) {
	// Generate default hostname
	if config.Hostname == "" {
		config.Hostname = id[:12]
	}
}

func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
	container.Lock()
	defer container.Unlock()
	return daemon.parseSecurityOpt(container, hostConfig)
}

func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
	// Do not lock while creating volumes since this could be calling out to external plugins
	// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
	if err := daemon.registerMountPoints(container, hostConfig); err != nil {
		return err
	}

	container.Lock()
	defer container.Unlock()

	// Register any links from the host config before starting the container
	if err := daemon.registerLinks(container, hostConfig); err != nil {
		return err
	}

	runconfig.SetDefaultNetModeIfBlank(hostConfig)
	container.HostConfig = hostConfig
	return container.CheckpointTo(daemon.containersReplica)
}

// verifyContainerSettings performs validation of the hostconfig and config
// structures.
func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) (warnings []string, err error) {
	// First perform verification of settings common across all platforms.
	if config != nil {
		if config.WorkingDir != "" {
			wdInvalid := false
			if runtime.GOOS == platform {
				config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
				if !system.IsAbs(config.WorkingDir) {
					wdInvalid = true
				}
			} else {
				// LCOW. Force Unix semantics
				config.WorkingDir = strings.Replace(config.WorkingDir, string(os.PathSeparator), "/", -1)
				if !path.IsAbs(config.WorkingDir) {
					wdInvalid = true
				}
			}
			if wdInvalid {
				return nil, fmt.Errorf("the working directory '%s' is invalid, it needs to be an absolute path", config.WorkingDir)
			}
		}

		if len(config.StopSignal) > 0 {
			_, err := signal.ParseSignal(config.StopSignal)
			if err != nil {
				return nil, err
			}
		}

		// Validate if Env contains empty variable or not (e.g., ``, `=foo`)
		for _, env := range config.Env {
			if _, err := opts.ValidateEnv(env); err != nil {
				return nil, err
			}
		}

		if err := validateHealthCheck(config.Healthcheck); err != nil {
			return nil, err
		}
	}

	if hostConfig == nil {
		return nil, nil
	}

	if hostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
		return nil, errors.Errorf("can't create 'AutoRemove' container with restart policy")
	}

	// Validate mounts; check if host directories still exist
	parser := volumemounts.NewParser(platform)
	for _, cfg := range hostConfig.Mounts {
		if err := parser.ValidateMountConfig(&cfg); err != nil {
			return nil, err
		}
	}

	for _, extraHost := range hostConfig.ExtraHosts {
		if _, err := opts.ValidateExtraHost(extraHost); err != nil {
			return nil, err
		}
	}

	for port := range hostConfig.PortBindings {
		_, portStr := nat.SplitProtoPort(string(port))
		if _, err := nat.ParsePort(portStr); err != nil {
			return nil, errors.Errorf("invalid port specification: %q", portStr)
		}
		for _, pb := range hostConfig.PortBindings[port] {
			_, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort))
			if err != nil {
				return nil, errors.Errorf("invalid port specification: %q", pb.HostPort)
			}
		}
	}

	if err := validateRestartPolicy(hostConfig.RestartPolicy); err != nil {
		return nil, err
	}
	if !hostConfig.Isolation.IsValid() {
		return nil, errors.Errorf("invalid isolation '%s' on %s", hostConfig.Isolation, runtime.GOOS)
	}

	// Now do platform-specific verification
	warnings, err = verifyPlatformContainerSettings(daemon, hostConfig, update)
	for _, w := range warnings {
		logrus.Warn(w)
	}
	return warnings, err
}

// validateHealthCheck validates the healthcheck params of Config
func validateHealthCheck(healthConfig *containertypes.HealthConfig) error {
	if healthConfig == nil {
		return nil
	}
	if healthConfig.Interval != 0 && healthConfig.Interval < containertypes.MinimumDuration {
		return errors.Errorf("Interval in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
	}
	if healthConfig.Timeout != 0 && healthConfig.Timeout < containertypes.MinimumDuration {
		return errors.Errorf("Timeout in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
	}
	if healthConfig.Retries < 0 {
		return errors.Errorf("Retries in Healthcheck cannot be negative")
	}
	if healthConfig.StartPeriod != 0 && healthConfig.StartPeriod < containertypes.MinimumDuration {
		return errors.Errorf("StartPeriod in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
	}
	return nil
}

func validateRestartPolicy(policy containertypes.RestartPolicy) error {
	switch policy.Name {
	case "always", "unless-stopped", "no":
		if policy.MaximumRetryCount != 0 {
			return errors.Errorf("maximum retry count cannot be used with restart policy '%s'", policy.Name)
		}
	case "on-failure":
		if policy.MaximumRetryCount < 0 {
			return errors.Errorf("maximum retry count cannot be negative")
		}
	case "":
		// do nothing
		return nil
	default:
		return errors.Errorf("invalid restart policy '%s'", policy.Name)
	}
	return nil
}
<commit_msg>Extract port-mapping validation to a function<commit_after>package daemon // import "github.com/docker/docker/daemon"

import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/strslice"
	"github.com/docker/docker/container"
	"github.com/docker/docker/daemon/network"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/image"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/signal"
	"github.com/docker/docker/pkg/system"
	"github.com/docker/docker/pkg/truncindex"
	"github.com/docker/docker/runconfig"
	volumemounts "github.com/docker/docker/volume/mounts"
	"github.com/docker/go-connections/nat"
	"github.com/opencontainers/selinux/go-selinux/label"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// GetContainer looks for a container using the provided information, which could be
// one of the following inputs from the caller:
//  - A full container ID, which will exact match a container in daemon's list
//  - A container name, which will only exact match via the GetByName() function
//  - A partial container ID prefix (e.g. short ID) of any length that is
//    unique enough to only return a single container object
//  If none of these searches succeed, an error is returned
func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, error) {
	if len(prefixOrName) == 0 {
		return nil, errors.WithStack(invalidIdentifier(prefixOrName))
	}

	if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil {
		// prefix is an exact match to a full container ID
		return containerByID, nil
	}

	// GetByName will match only an exact name provided; we ignore errors
	if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil {
		// prefix is an exact match to a full container Name
		return containerByName, nil
	}

	containerID, indexError := daemon.idIndex.Get(prefixOrName)
	if indexError != nil {
		// When truncindex defines an error type, use that instead
		if indexError == truncindex.ErrNotExist {
			return nil, containerNotFound(prefixOrName)
		}
		return nil, errdefs.System(indexError)
	}
	return daemon.containers.Get(containerID), nil
}

// checkContainer make sure the specified container validates the specified conditions
func (daemon *Daemon) checkContainer(container *container.Container, conditions ...func(*container.Container) error) error {
	for _, condition := range conditions {
		if err := condition(container); err != nil {
			return err
		}
	}
	return nil
}

// Exists returns a true if a container of the specified ID or name exists,
// false otherwise.
func (daemon *Daemon) Exists(id string) bool {
	c, _ := daemon.GetContainer(id)
	return c != nil
}

// IsPaused returns a bool indicating if the specified container is paused.
func (daemon *Daemon) IsPaused(id string) bool {
	c, _ := daemon.GetContainer(id)
	return c.State.IsPaused()
}

func (daemon *Daemon) containerRoot(id string) string {
	return filepath.Join(daemon.repository, id)
}

// Load reads the contents of a container from disk
// This is typically done at startup.
func (daemon *Daemon) load(id string) (*container.Container, error) {
	container := daemon.newBaseContainer(id)

	if err := container.FromDisk(); err != nil {
		return nil, err
	}
	if err := label.ReserveLabel(container.ProcessLabel); err != nil {
		return nil, err
	}

	if container.ID != id {
		return container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
	}

	return container, nil
}

// Register makes a container object usable by the daemon as <container.ID>
func (daemon *Daemon) Register(c *container.Container) error {
	// Attach to stdout and stderr
	if c.Config.OpenStdin {
		c.StreamConfig.NewInputPipes()
	} else {
		c.StreamConfig.NewNopInputPipe()
	}

	// once in the memory store it is visible to other goroutines
	// grab a Lock until it has been checkpointed to avoid races
	c.Lock()
	defer c.Unlock()

	daemon.containers.Add(c.ID, c)
	daemon.idIndex.Add(c.ID)
	return c.CheckpointTo(daemon.containersReplica)
}

func (daemon *Daemon) newContainer(name string, operatingSystem string, config *containertypes.Config, hostConfig *containertypes.HostConfig, imgID image.ID, managed bool) (*container.Container, error) {
	var (
		id             string
		err            error
		noExplicitName = name == ""
	)
	id, name, err = daemon.generateIDAndName(name)
	if err != nil {
		return nil, err
	}

	if hostConfig.NetworkMode.IsHost() {
		if config.Hostname == "" {
			config.Hostname, err = os.Hostname()
			if err != nil {
				return nil, errdefs.System(err)
			}
		}
	} else {
		daemon.generateHostname(id, config)
	}
	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)

	base := daemon.newBaseContainer(id)
	base.Created = time.Now().UTC()
	base.Managed = managed
	base.Path = entrypoint
	base.Args = args //FIXME: de-duplicate from config
	base.Config = config
	base.HostConfig = &containertypes.HostConfig{}
	base.ImageID = imgID
	base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName}
	base.Name = name
	base.Driver = daemon.imageService.GraphDriverForOS(operatingSystem)
	base.OS = operatingSystem
	return base, err
}

// GetByName returns a container given a name.
func (daemon *Daemon) GetByName(name string) (*container.Container, error) {
	if len(name) == 0 {
		return nil, fmt.Errorf("No container name supplied")
	}
	fullName := name
	if name[0] != '/' {
		fullName = "/" + name
	}
	id, err := daemon.containersReplica.Snapshot().GetID(fullName)
	if err != nil {
		return nil, fmt.Errorf("Could not find entity for %s", name)
	}
	e := daemon.containers.Get(id)
	if e == nil {
		return nil, fmt.Errorf("Could not find container for entity id %s", id)
	}
	return e, nil
}

// newBaseContainer creates a new container with its initial
// configuration based on the root storage from the daemon.
func (daemon *Daemon) newBaseContainer(id string) *container.Container {
	return container.NewBaseContainer(id, daemon.containerRoot(id))
}

func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) {
	if len(configEntrypoint) != 0 {
		return configEntrypoint[0], append(configEntrypoint[1:], configCmd...)
	}
	return configCmd[0], configCmd[1:]
}

func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) {
	// Generate default hostname
	if config.Hostname == "" {
		config.Hostname = id[:12]
	}
}

func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error {
	container.Lock()
	defer container.Unlock()
	return daemon.parseSecurityOpt(container, hostConfig)
}

func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error {
	// Do not lock while creating volumes since this could be calling out to external plugins
	// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
	if err := daemon.registerMountPoints(container, hostConfig); err != nil {
		return err
	}

	container.Lock()
	defer container.Unlock()

	// Register any links from the host config before starting the container
	if err := daemon.registerLinks(container, hostConfig); err != nil {
		return err
	}

	runconfig.SetDefaultNetModeIfBlank(hostConfig)
	container.HostConfig = hostConfig
	return container.CheckpointTo(daemon.containersReplica)
}

// verifyContainerSettings performs validation of the hostconfig and config
// structures.
func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) (warnings []string, err error) {
	// First perform verification of settings common across all platforms.
	if config != nil {
		if config.WorkingDir != "" {
			wdInvalid := false
			if runtime.GOOS == platform {
				config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
				if !system.IsAbs(config.WorkingDir) {
					wdInvalid = true
				}
			} else {
				// LCOW. Force Unix semantics
				config.WorkingDir = strings.Replace(config.WorkingDir, string(os.PathSeparator), "/", -1)
				if !path.IsAbs(config.WorkingDir) {
					wdInvalid = true
				}
			}
			if wdInvalid {
				return nil, fmt.Errorf("the working directory '%s' is invalid, it needs to be an absolute path", config.WorkingDir)
			}
		}

		if len(config.StopSignal) > 0 {
			_, err := signal.ParseSignal(config.StopSignal)
			if err != nil {
				return nil, err
			}
		}

		// Validate if Env contains empty variable or not (e.g., ``, `=foo`)
		for _, env := range config.Env {
			if _, err := opts.ValidateEnv(env); err != nil {
				return nil, err
			}
		}

		if err := validateHealthCheck(config.Healthcheck); err != nil {
			return nil, err
		}
	}

	if hostConfig == nil {
		return nil, nil
	}

	if hostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
		return nil, errors.Errorf("can't create 'AutoRemove' container with restart policy")
	}

	// Validate mounts; check if host directories still exist
	parser := volumemounts.NewParser(platform)
	for _, cfg := range hostConfig.Mounts {
		if err := parser.ValidateMountConfig(&cfg); err != nil {
			return nil, err
		}
	}

	for _, extraHost := range hostConfig.ExtraHosts {
		if _, err := opts.ValidateExtraHost(extraHost); err != nil {
			return nil, err
		}
	}

	if err := validatePortBindings(hostConfig.PortBindings); err != nil {
		return nil, err
	}
	if err := validateRestartPolicy(hostConfig.RestartPolicy); err != nil {
		return nil, err
	}
	if !hostConfig.Isolation.IsValid() {
		return nil, errors.Errorf("invalid isolation '%s' on %s", hostConfig.Isolation, runtime.GOOS)
	}

	// Now do platform-specific verification
	warnings, err = verifyPlatformContainerSettings(daemon, hostConfig, update)
	for _, w := range warnings {
		logrus.Warn(w)
	}
	return warnings, err
}

// validateHealthCheck validates the healthcheck params of Config
func validateHealthCheck(healthConfig *containertypes.HealthConfig) error {
	if healthConfig == nil {
		return nil
	}
	if healthConfig.Interval != 0 && healthConfig.Interval < containertypes.MinimumDuration {
		return errors.Errorf("Interval in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
	}
	if healthConfig.Timeout != 0 && healthConfig.Timeout < containertypes.MinimumDuration {
		return errors.Errorf("Timeout in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
	}
	if healthConfig.Retries < 0 {
		return errors.Errorf("Retries in Healthcheck cannot be negative")
	}
	if healthConfig.StartPeriod != 0 && healthConfig.StartPeriod < containertypes.MinimumDuration {
		return errors.Errorf("StartPeriod in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
	}
	return nil
}

func validatePortBindings(ports nat.PortMap) error {
	for port := range ports {
		_, portStr := nat.SplitProtoPort(string(port))
		if _, err := nat.ParsePort(portStr); err != nil {
			return errors.Errorf("invalid port specification: %q", portStr)
		}
		for _, pb := range ports[port] {
			_, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort))
			if err != nil {
				return errors.Errorf("invalid port specification: %q", pb.HostPort)
			}
		}
	}
	return nil
}

func validateRestartPolicy(policy containertypes.RestartPolicy) error {
	switch policy.Name {
	case "always", "unless-stopped", "no":
		if policy.MaximumRetryCount != 0 {
			return errors.Errorf("maximum retry count cannot be used with restart policy '%s'", policy.Name)
		}
	case "on-failure":
		if policy.MaximumRetryCount < 0 {
			return errors.Errorf("maximum retry count cannot be negative")
		}
	case "":
		// do nothing
		return nil
	default:
		return errors.Errorf("invalid restart policy '%s'", policy.Name)
	}
	return nil
}
<|endoftext|>


<commit_before>package daemon

import (
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/discovery"

	// Register the libkv backends for discovery.
	_ "github.com/docker/docker/pkg/discovery/kv"
)

const (
	// defaultDiscoveryHeartbeat is the default value for discovery heartbeat interval.
	defaultDiscoveryHeartbeat = 20 * time.Second

	// defaultDiscoveryTTL is the default TTL interface for discovery.
	defaultDiscoveryTTL = 60 * time.Second
)

// initDiscovery initialized the nodes discovery subsystem by connecting to the specified backend
// and start a registration loop to advertise the current node under the specified address.
func initDiscovery(backend, address string, clusterOpts map[string]string) (discovery.Backend, error) {
	var (
		discoveryBackend discovery.Backend
		err              error
	)
	if discoveryBackend, err = discovery.New(backend, defaultDiscoveryHeartbeat, defaultDiscoveryTTL, clusterOpts); err != nil {
		return nil, err
	}

	// We call Register() on the discovery backend in a loop for the whole lifetime of the daemon,
	// but we never actually Watch() for nodes appearing and disappearing for the moment.
	go registrationLoop(discoveryBackend, address)
	return discoveryBackend, nil
}

// registrationLoop registers the current node against the discovery backend using the specified
// address. The function never returns, as registration against the backend comes with a TTL and
// requires regular heartbeats.
func registrationLoop(discoveryBackend discovery.Backend, address string) {
	for {
		if err := discoveryBackend.Register(address); err != nil {
			log.Errorf("Registering as %q in discovery failed: %v", address, err)
		}
		time.Sleep(defaultDiscoveryHeartbeat)
	}
}
<commit_msg>Refactoring in daemon/discovery.go<commit_after>package daemon

import (
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/discovery"

	// Register the libkv backends for discovery.
	_ "github.com/docker/docker/pkg/discovery/kv"
)

const (
	// defaultDiscoveryHeartbeat is the default value for discovery heartbeat interval.
	defaultDiscoveryHeartbeat = 20 * time.Second

	// defaultDiscoveryTTL is the default TTL interface for discovery.
	defaultDiscoveryTTL = 60 * time.Second
)

// initDiscovery initialized the nodes discovery subsystem by connecting to the specified backend
// and start a registration loop to advertise the current node under the specified address.
func initDiscovery(backend, address string, clusterOpts map[string]string) (discovery.Backend, error) {
	discoveryBackend, err := discovery.New(backend, defaultDiscoveryHeartbeat, defaultDiscoveryTTL, clusterOpts)
	if err != nil {
		return nil, err
	}

	// We call Register() on the discovery backend in a loop for the whole lifetime of the daemon,
	// but we never actually Watch() for nodes appearing and disappearing for the moment.
	go registrationLoop(discoveryBackend, address)
	return discoveryBackend, nil
}

func registerAddr(backend discovery.Backend, addr string) {
	if err := backend.Register(addr); err != nil {
		log.Warnf("Registering as %q in discovery failed: %v", addr, err)
	}
}

// registrationLoop registers the current node against the discovery backend using the specified
// address. The function never returns, as registration against the backend comes with a TTL and
// requires regular heartbeats.
func registrationLoop(discoveryBackend discovery.Backend, address string) {
	registerAddr(discoveryBackend, address)
	for range time.Tick(defaultDiscoveryHeartbeat) {
		registerAddr(discoveryBackend, address)
	}
}
<|endoftext|>


<commit_before>package gcssync

import (
	"code.google.com/p/google-api-go-client/storage/v1"
	"fmt"
	"github.com/dustin/go-humanize"
	"os"
	"path/filepath"
	"sync"
	"time"
)

const (
	fileWalkerBufferSize = 20
	fileWalkerEstimate   = 500
	uploadGoroutinesNum  = 10
)

type fileInfo struct {
	info os.FileInfo
	path string
}

func getLocalFiles(dirname string) []fileInfo {
	rawFiles := make(chan fileInfo, fileWalkerBufferSize)
	var done sync.WaitGroup

	done.Add(1)
	go func() {
		filepath.Walk(dirname, func(path string, f os.FileInfo, err error) error {
			if err == nil && !f.IsDir() {
				rel, _ := filepath.Rel(dirname, path)
				rawFiles <- fileInfo{
					info: f,
					path: rel,
				}
			}
			return nil
		})
		close(rawFiles)
		done.Done()
	}()

	result := make([]fileInfo, 0, fileWalkerEstimate)

	// this is unnecessary, but left there in case filters for files will be implemented
	done.Add(1)
	go func() {
		for {
			f, more := <-rawFiles
			if more {
				result = append(result, f)
			} else {
				done.Done()
				return
			}
		}
	}()
	done.Wait()
	return result
}

func (c *Client) SyncFolder(from, to string) {
	fmt.Println(from, to)
	var localFiles []fileInfo
	var listsFetched sync.WaitGroup

	listsFetched.Add(1)
	go func() {
		localFiles = getLocalFiles(from)
		listsFetched.Done()
	}()

	var objects []*storage.Object
	var err error

	listsFetched.Add(1)
	go func() {
		objects, err = c.ListFiles()
		if err != nil {
			fmt.Println(err)
		}
		listsFetched.Done()
	}()

	listsFetched.Wait()

	fmt.Printf("Found %d local files\n", len(localFiles))
	fmt.Printf("Found %d remote files\n", len(objects))

	remoteCache := make(map[string]time.Time, len(objects))

	for _, object := range objects {
		time, err := time.Parse(time.RFC3339, object.Updated)
		if err != nil {
			continue
		}
		remoteCache[object.Name] = time
	}

	already := 0
	created := 0
	update := 0

	toDo := make([]fileInfo, 0, len(localFiles))

	for _, file := range localFiles {
		remoteTime, exists := remoteCache[file.path]
		if exists {
			already++
			if file.info.ModTime().After(remoteTime) {
				toDo = append(toDo, file)
				update++
			}
		} else {
			created++
			toDo = append(toDo, file)
		}
	}

	var uploadDone sync.WaitGroup
	uploadFile := make(chan fileInfo, uploadGoroutinesNum)
	uploadDone.Add(1)
	go func() {
		for _, file := range toDo {
			uploadFile <- file
		}
		close(uploadFile)
		uploadDone.Done()
	}()

	var transferedBytes uint64 = 0
	transfered := make(chan uint64)

	go func() {
		for {
			transferedBytes += <-transfered
		}
	}()

	for i := 0; i < uploadGoroutinesNum; i++ {
		uploadDone.Add(1)
		go func() {
			for {
				file, more := <-uploadFile
				if more {
					success, object, err := c.UploadFile(filepath.Join(from, file.path), file.path)
					if err != nil {
						fmt.Println(err)
						fmt.Println(object.Name)
					}
					if err != nil || success == false {
						fmt.Println(err)
					} else {
						transfered <- object.Size
						fmt.Printf("Uploaded %s %s\n", object.Name, humanize.Bytes(object.Size))
					}
				} else {
					uploadDone.Done()
					return
				}
			}
		}()
	}

	uploadDone.Wait()

	fmt.Printf("Processed %d files, uploaded %s\n", len(toDo), humanize.Bytes(transferedBytes))
	fmt.Printf("Already uploaded: %d, newly created: %d, updated: %d\n", already, created, update)
}
<commit_msg>refractor(sync): to net set new variable to inital value<commit_after>package gcssync

import (
	"code.google.com/p/google-api-go-client/storage/v1"
	"fmt"
	"github.com/dustin/go-humanize"
	"os"
	"path/filepath"
	"sync"
	"time"
)

const (
	fileWalkerBufferSize = 20
	fileWalkerEstimate   = 500
	uploadGoroutinesNum  = 10
)

type fileInfo struct {
	info os.FileInfo
	path string
}

func getLocalFiles(dirname string) []fileInfo {
	rawFiles := make(chan fileInfo, fileWalkerBufferSize)
	var done sync.WaitGroup

	done.Add(1)
	go func() {
		filepath.Walk(dirname, func(path string, f os.FileInfo, err error) error {
			if err == nil && !f.IsDir() {
				rel, _ := filepath.Rel(dirname, path)
				rawFiles <- fileInfo{
					info: f,
					path: rel,
				}
			}
			return nil
		})
		close(rawFiles)
		done.Done()
	}()

	result := make([]fileInfo, 0, fileWalkerEstimate)

	// this is unnecessary, but left there in case filters for files will be implemented
	done.Add(1)
	go func() {
		for {
			f, more := <-rawFiles
			if more {
				result = append(result, f)
			} else {
				done.Done()
				return
			}
		}
	}()
	done.Wait()
	return result
}

func (c *Client) SyncFolder(from, to string) {
	fmt.Println(from, to)
	var localFiles []fileInfo
	var listsFetched sync.WaitGroup

	listsFetched.Add(1)
	go func() {
		localFiles = getLocalFiles(from)
		listsFetched.Done()
	}()

	var objects []*storage.Object
	var err error

	listsFetched.Add(1)
	go func() {
		objects, err = c.ListFiles()
		if err != nil {
			fmt.Println(err)
		}
		listsFetched.Done()
	}()

	listsFetched.Wait()

	fmt.Printf("Found %d local files\n", len(localFiles))
	fmt.Printf("Found %d remote files\n", len(objects))

	remoteCache := make(map[string]time.Time, len(objects))

	for _, object := range objects {
		time, err := time.Parse(time.RFC3339, object.Updated)
		if err != nil {
			continue
		}
		remoteCache[object.Name] = time
	}

	already := 0
	created := 0
	update := 0

	toDo := make([]fileInfo, 0, len(localFiles))

	for _, file := range localFiles {
		remoteTime, exists := remoteCache[file.path]
		if exists {
			already++
			if file.info.ModTime().After(remoteTime) {
				toDo = append(toDo, file)
				update++
			}
		} else {
			created++
			toDo = append(toDo, file)
		}
	}

	var uploadDone sync.WaitGroup
	uploadFile := make(chan fileInfo, uploadGoroutinesNum)
	uploadDone.Add(1)
	go func() {
		for _, file := range toDo {
			uploadFile <- file
		}
		close(uploadFile)
		uploadDone.Done()
	}()

	var transferedBytes uint64
	transfered := make(chan uint64)

	go func() {
		for {
			transferedBytes += <-transfered
		}
	}()

	for i := 0; i < uploadGoroutinesNum; i++ {
		uploadDone.Add(1)
		go func() {
			for {
				file, more := <-uploadFile
				if more {
					success, object, err := c.UploadFile(filepath.Join(from, file.path), file.path)
					if err != nil {
						fmt.Println(err)
						fmt.Println(object.Name)
					}
					if err != nil || success == false {
						fmt.Println(err)
					} else {
						transfered <- object.Size
						fmt.Printf("Uploaded %s %s\n", object.Name, humanize.Bytes(object.Size))
					}
				} else {
					uploadDone.Done()
					return
				}
			}
		}()
	}

	uploadDone.Wait()

	fmt.Printf("Processed %d files, uploaded %s\n", len(toDo), humanize.Bytes(transferedBytes))
	fmt.Printf("Already uploaded: %d, newly created: %d, updated: %d\n", already, created, update)
}
<|endoftext|>