protoc-gen-go: add paths=source_relative option (#544)

When --go_out=paths=source_relative:., output filenames are always
derived from the input filenames. For example, the output file
for a/b/c.proto will always be a/b/c.pb.go, regardless of the
presence or absence of a go_package option in the input file.

Fixes #515.
diff --git a/README.md b/README.md
index 1b09ad7..01b29da 100644
--- a/README.md
+++ b/README.md
@@ -56,13 +56,49 @@
 The generated files will be suffixed .pb.go.  See the Test code below
 for an example using such a file.
 
+## Packages and input paths ##
+
+The protocol buffer language has a concept of "packages" which does not
+correspond well to the Go notion of packages. In generated Go code,
+each source `.proto` file is associated with a single Go package. The
+name and import path for this package is specified with the `go_package`
+proto option:
+
+	option go_package = "github.com/golang/protobuf/ptypes/any";
+
+The protocol buffer compiler will attempt to derive a package name and
+import path if a `go_package` option is not present, but it is
+best to always specify one explicitly.
+
+There is a one-to-one relationship between source `.proto` files and
+generated `.pb.go` files, but any number of `.pb.go` files may be
+contained in the same Go package.
+
+The output name of a generated file is produced by replacing the
+`.proto` suffix with `.pb.go` (e.g., `foo.proto` produces `foo.pb.go`).
+However, the output directory is selected in one of two ways.  Let
+us say we have `inputs/x.proto` with a `go_package` option of
+`github.com/golang/protobuf/p`. The corresponding output file may
+be:
+
+- Relative to the import path:
+
+	protoc --go_out=. inputs/x.proto
+	# writes ./github.com/golang/protobuf/p/x.pb.go
+
+  (This can work well with `--go_out=$GOPATH`.)
+
+- Relative to the input file:
+
+	protoc --go_out=paths=source_relative:. inputs/x.proto
+	# generate ./inputs/x.pb.go
+
+## Generated code ##
 
 The package comment for the proto library contains text describing
 the interface provided in Go for protocol buffers. Here is an edited
 version.
 
-==========
-
 The proto package converts data structures to and from the
 wire format of protocol buffers.  It works in concert with the
 Go source code generated for .proto files by the protocol compiler.
@@ -170,22 +206,25 @@
 To pass extra parameters to the plugin, use a comma-separated
 parameter list separated from the output directory by a colon:
 
-
 	protoc --go_out=plugins=grpc,import_path=mypackage:. *.proto
 
-
-- `import_prefix=xxx` - a prefix that is added onto the beginning of
-  all imports. Useful for things like generating protos in a
-  subdirectory, or regenerating vendored protobufs in-place.
-- `import_path=foo/bar` - used as the package if no input files
-  declare `go_package`. If it contains slashes, everything up to the
-  rightmost slash is ignored.
+- `paths=(import | source_relative)` - specifies how the paths of
+  generated files are structured. See the "Packages and imports paths"
+  section above. The default is `import`.
 - `plugins=plugin1+plugin2` - specifies the list of sub-plugins to
   load. The only plugin in this repo is `grpc`.
 - `Mfoo/bar.proto=quux/shme` - declares that foo/bar.proto is
   associated with Go package quux/shme.  This is subject to the
   import_prefix parameter.
 
+The following parameters are deprecated and should not be used:
+
+- `import_prefix=xxx` - a prefix that is added onto the beginning of
+  all imports.
+- `import_path=foo/bar` - used as the package if no input files
+  declare `go_package`. If it contains slashes, everything up to the
+  rightmost slash is ignored.
+
 ## gRPC Support ##
 
 If a proto file specifies RPC services, protoc-gen-go can be instructed to
diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go
index 89c1cde..f943322 100644
--- a/protoc-gen-go/generator/generator.go
+++ b/protoc-gen-go/generator/generator.go
@@ -324,13 +324,17 @@
 }
 
 // goFileName returns the output name for the generated Go file.
-func (d *FileDescriptor) goFileName() string {
+func (d *FileDescriptor) goFileName(pathType pathType) string {
 	name := *d.Name
 	if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
 		name = name[:len(name)-len(ext)]
 	}
 	name += ".pb.go"
 
+	if pathType == pathTypeSourceRelative {
+		return name
+	}
+
 	// Does the file have a "go_package" option?
 	// If it does, it may override the filename.
 	if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
@@ -574,11 +578,19 @@
 	typeNameToObject map[string]Object              // Key is a fully-qualified name in input syntax.
 	init             []string                       // Lines to emit in the init function.
 	indent           string
+	pathType         pathType // How to generate output filenames.
 	writeOutput      bool
 	annotateCode     bool                                       // whether to store annotations
 	annotations      []*descriptor.GeneratedCodeInfo_Annotation // annotations to store
 }
 
+type pathType int
+
+const (
+	pathTypeImport pathType = iota
+	pathTypeSourceRelative
+)
+
 // New creates a new generator and allocates the request and response protobufs.
 func New() *Generator {
 	g := new(Generator)
@@ -623,6 +635,15 @@
 			g.ImportPrefix = GoImportPath(v)
 		case "import_path":
 			g.PackageImportPath = v
+		case "paths":
+			switch v {
+			case "import":
+				g.pathType = pathTypeImport
+			case "source_relative":
+				g.pathType = pathTypeSourceRelative
+			default:
+				g.Fail(fmt.Sprintf(`Unknown path type %q: want "import" or "source_relative".`, v))
+			}
 		case "plugins":
 			pluginList = v
 		case "annotate_code":
@@ -1206,7 +1227,7 @@
 		if !g.writeOutput {
 			continue
 		}
-		fname := file.goFileName()
+		fname := file.goFileName(g.pathType)
 		g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
 			Name:    proto.String(fname),
 			Content: proto.String(g.String()),
@@ -1215,7 +1236,7 @@
 			// Store the generated code annotations in text, as the protoc plugin protocol requires that
 			// strings contain valid UTF-8.
 			g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
-				Name:    proto.String(file.goFileName() + ".meta"),
+				Name:    proto.String(file.goFileName(g.pathType) + ".meta"),
 				Content: proto.String(proto.CompactTextString(&descriptor.GeneratedCodeInfo{Annotation: g.annotations})),
 			})
 		}
diff --git a/protoc-gen-go/golden_test.go b/protoc-gen-go/golden_test.go
index 77039bd..7c30017 100644
--- a/protoc-gen-go/golden_test.go
+++ b/protoc-gen-go/golden_test.go
@@ -51,13 +51,12 @@
 
 	// Compile each package, using this binary as protoc-gen-go.
 	for _, sources := range packages {
-		args := []string{"-Itestdata", "--go_out=plugins=grpc:" + workdir}
+		args := []string{"-Itestdata", "--go_out=plugins=grpc,paths=source_relative:" + workdir}
 		args = append(args, sources...)
 		protoc(t, args)
 	}
 
 	// Compare each generated file to the golden version.
-	relRoot := filepath.Join(workdir, "github.com/golang/protobuf/protoc-gen-go/testdata")
 	filepath.Walk(workdir, func(genPath string, info os.FileInfo, _ error) error {
 		if info.IsDir() {
 			return nil
@@ -65,13 +64,13 @@
 
 		// For each generated file, figure out the path to the corresponding
 		// golden file in the testdata directory.
-		relPath, err := filepath.Rel(relRoot, genPath)
+		relPath, err := filepath.Rel(workdir, genPath)
 		if err != nil {
-			t.Errorf("filepath.Rel(%q, %q): %v", relRoot, genPath, err)
+			t.Errorf("filepath.Rel(%q, %q): %v", workdir, genPath, err)
 			return nil
 		}
 		if filepath.SplitList(relPath)[0] == ".." {
-			t.Errorf("generated file %q is not relative to %q", genPath, relRoot)
+			t.Errorf("generated file %q is not relative to %q", genPath, workdir)
 		}
 		goldenPath := filepath.Join("testdata", relPath)
 
@@ -180,6 +179,19 @@
 			// import_prefix applies after M.
 			"prefixpackage/gamma": true,
 		},
+	}, {
+		parameters: "paths=source_relative",
+		wantFiles: map[string]bool{
+			"alpha/a.pb.go": true,
+			"beta/b.pb.go":  true,
+		},
+	}, {
+		parameters: "paths=source_relative,import_prefix=prefix",
+		wantFiles: map[string]bool{
+			// import_prefix doesn't affect filenames.
+			"alpha/a.pb.go": true,
+			"beta/b.pb.go":  true,
+		},
 	}} {
 		name := test.parameters
 		if name == "" {