Repository: etcd-io/etcd
File: server/storage/wal/version.go (Go)

Code before:
//     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 wal

import (
	"fmt"
	"strings"

	"github.com/coreos/go-semver/semver"
	"github.com/golang/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
	"google.golang.org/protobuf/types/descriptorpb"

	"go.etcd.io/etcd/api/v3/etcdserverpb"
	"go.etcd.io/etcd/api/v3/version"
	"go.etcd.io/etcd/pkg/v3/pbutil"
	"go.etcd.io/raft/v3/raftpb"
)

type WALVersion interface {
	// MinimalEtcdVersion returns minimal etcd version able to interpret WAL log.
	MinimalEtcdVersion() *semver.Version
}

// ReadWALVersion reads remaining entries from opened WAL and returns struct
// that implements schema.WAL interface.
func ReadWALVersion(w *WAL) (WALVersion, error) {
	_, _, ents, err := w.ReadAll()
	if err != nil {
		return nil, err
	}
	return &walVersion{entries: ents}, nil
}

type walVersion struct {
	entries []raftpb.Entry
}

// MinimalEtcdVersion returns minimal etcd able to interpret entries from  WAL log,
func (w *walVersion) MinimalEtcdVersion() *semver.Version {
	return MinimalEtcdVersion(w.entries)
}

// MinimalEtcdVersion returns minimal etcd able to interpret entries from  WAL log,
// determined by looking at entries since the last snapshot and returning the highest

Review comment (suggestion):
If we later consider enabling the `exported` golangci-lint linter, this will generate an error. I think it should be better named `Version`, so it can be used by `wal.Version` instead of `wal.WALVersion`. Note: we still keep it named `WALVersion` in `storage/schema`.

Code after:
//     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 wal

import (
	"fmt"
	"strings"

	"github.com/coreos/go-semver/semver"
	"github.com/golang/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
	"google.golang.org/protobuf/types/descriptorpb"

	"go.etcd.io/etcd/api/v3/etcdserverpb"
	"go.etcd.io/etcd/api/v3/version"
	"go.etcd.io/etcd/pkg/v3/pbutil"
	"go.etcd.io/raft/v3/raftpb"
)

// ReadWALVersion reads remaining entries from opened WAL and returns struct
// that implements schema.WAL interface.
func ReadWALVersion(w *WAL) (*walVersion, error) {
	_, _, ents, err := w.ReadAll()
	if err != nil {
		return nil, err
	}
	return &walVersion{entries: ents}, nil
}

type walVersion struct {
	entries []raftpb.Entry
}

// MinimalEtcdVersion returns minimal etcd able to interpret entries from  WAL log,
func (w *walVersion) MinimalEtcdVersion() *semver.Version {
	return MinimalEtcdVersion(w.entries)
}

// MinimalEtcdVersion returns minimal etcd able to interpret entries from  WAL log,
// determined by looking at entries since the last snapshot and returning the highest
// etcd version annotation from used messages, fields, enums and their values.
func MinimalEtcdVersion(ents []raftpb.Entry) *semver.Version {
	var maxVer *semver.Version
	for _, ent := range ents {
		err := visitEntry(ent, func(path protoreflect.FullName, ver *semver.Version) error {