<commit_before>// package multistream implements a peerstream transport using
// go-multistream to select the underlying stream muxer
package multistream

import (
	"net"

	mss "gx/ipfs/Qmf91yhgRLo2dhhbc5zZ7TxjMaR1oxaWaoc9zRZdi1kU4a/go-multistream"

	smux "github.com/jbenet/go-stream-muxer"
)

type Transport struct {
	mux *mss.MultistreamMuxer

	tpts map[string]smux.Transport

	OrderPreference []string
}

func NewBlankTransport() *Transport {
	return &Transport{
		mux:  mss.NewMultistreamMuxer(),
		tpts: make(map[string]smux.Transport),
	}
}

func (t *Transport) AddTransport(path string, tpt smux.Transport) {
	t.mux.AddHandler(path, nil)
	t.tpts[path] = tpt
	t.OrderPreference = append(t.OrderPreference, path)
}

func (t *Transport) NewConn(nc net.Conn, isServer bool) (smux.Conn, error) {
	var proto string
	if isServer {
		selected, _, err := t.mux.Negotiate(nc)
		if err != nil {
			return nil, err
		}
		proto = selected
	} else {
		selected, err := mss.SelectOneOf(t.OrderPreference, nc)
		if err != nil {
			return nil, err
		}
		proto = selected
	}

	tpt := t.tpts[proto]

	return tpt.NewConn(nc, isServer)
}
<commit_msg>gx publish version 1.0.0<commit_after>// package multistream implements a peerstream transport using
// go-multistream to select the underlying stream muxer
package multistream

import (
	"net"

	mss "github.com/whyrusleeping/go-multistream"

	smux "github.com/jbenet/go-stream-muxer"
)

type Transport struct {
	mux *mss.MultistreamMuxer

	tpts map[string]smux.Transport

	OrderPreference []string
}

func NewBlankTransport() *Transport {
	return &Transport{
		mux:  mss.NewMultistreamMuxer(),
		tpts: make(map[string]smux.Transport),
	}
}

func (t *Transport) AddTransport(path string, tpt smux.Transport) {
	t.mux.AddHandler(path, nil)
	t.tpts[path] = tpt
	t.OrderPreference = append(t.OrderPreference, path)
}

func (t *Transport) NewConn(nc net.Conn, isServer bool) (smux.Conn, error) {
	var proto string
	if isServer {
		selected, _, err := t.mux.Negotiate(nc)
		if err != nil {
			return nil, err
		}
		proto = selected
	} else {
		selected, err := mss.SelectOneOf(t.OrderPreference, nc)
		if err != nil {
			return nil, err
		}
		proto = selected
	}

	tpt := t.tpts[proto]

	return tpt.NewConn(nc, isServer)
}
<|endoftext|>


<commit_before>package serviceenv

// Configuration is the generic configuration structure used to access configuration fields.
type Configuration struct {
	*GlobalConfiguration
	*PachdSpecificConfiguration
	*WorkerSpecificConfiguration
}

// GlobalConfiguration contains the global configuration.
type GlobalConfiguration struct {
	FeatureFlags
	EtcdHost            string `env:"ETCD_SERVICE_HOST,required"`
	EtcdPort            string `env:"ETCD_SERVICE_PORT,required"`
	PPSWorkerPort       uint16 `env:"PPS_WORKER_GRPC_PORT,default=1080"`
	Port                uint16 `env:"PORT,default=1650"`
	PeerPort            uint16 `env:"PEER_PORT,default=1653"`
	S3GatewayPort       uint16 `env:"S3GATEWAY_PORT,default=1600"`
	PPSEtcdPrefix       string `env:"PPS_ETCD_PREFIX,default=pachyderm_pps"`
	Namespace           string `env:"PACH_NAMESPACE,default=default"`
	StorageRoot         string `env:"PACH_ROOT,default=/pach"`
	GCPercent           int    `env:"GC_PERCENT,default=50"`
	LokiHost            string `env:"LOKI_SERVICE_HOST"`
	LokiPort            string `env:"LOKI_SERVICE_PORT"`
	OidcPort            uint16 `env:"OIDC_PORT,default=1657"`
	PostgresServiceHost string `env:"POSTGRES_SERVICE_HOST"`
	PostgresServicePort int    `env:"POSTGRES_SERVICE_PORT"`
	PostgresServiceSSL  string `env:"POSTGRES_SERVICE_SSL,default=disable"`
	PostgresDBName      string `env:"POSTGRES_DATABASE_NAME"`

	EtcdPrefix           string `env:"ETCD_PREFIX,default="`
	DeploymentID         string `env:"CLUSTER_DEPLOYMENT_ID,default="`
	LogLevel             string `env:"LOG_LEVEL,default=info"`
	AuthEtcdPrefix       string `env:"PACHYDERM_AUTH_ETCD_PREFIX,default=pachyderm_auth"`
	IdentityEtcdPrefix   string `env:"PACHYDERM_IDENTITY_ETCD_PREFIX,default=pachyderm_identity"`
	EnterpriseEtcdPrefix string `env:"PACHYDERM_ENTERPRISE_ETCD_PREFIX,default=pachyderm_enterprise"`
	Metrics              bool   `env:"METRICS,default=true"`
	MetricsEndpoint      string `env:"METRICS_ENDPOINT,default="`

	// SessionDurationMinutes it how long auth tokens are valid for, defaults to 30 days (30 * 24 * 60)
	SessionDurationMinutes int `env:"SESSION_DURATION_MINUTES,default=43200"`

	IdentityServerDatabase string `env:"IDENTITY_SERVER_DATABASE,default=dex"`
	IdentityServerUser     string `env:"IDENTITY_SERVER_USER,default=postgres"`
	IdentityServerPassword string `env:"IDENTITY_SERVER_PASSWORD"`

	// PPSSpecCommitID and PPSPipelineName are only set for workers and sidecar
	// pachd instances. Because both pachd and worker need to know the spec commit
	// (the worker so that it can avoid jobs for other versions of the same pipelines
	// and the sidecar so that it can serve the S3 gateway) it's stored in the
	// GlobalConfiguration, but it isn't set in a cluster's main pachd containers.
	PPSSpecCommitID string `env:"PPS_SPEC_COMMIT"`
	// The name of the pipeline that this worker belongs to
	PPSPipelineName string `env:"PPS_PIPELINE_NAME"`
}

// PachdFullConfiguration contains the full pachd configuration.
type PachdFullConfiguration struct {
	GlobalConfiguration
	PachdSpecificConfiguration
}

// PachdSpecificConfiguration contains the pachd specific configuration.
type PachdSpecificConfiguration struct {
	StorageConfiguration
	StorageBackend             string `env:"STORAGE_BACKEND,required"`
	StorageHostPath            string `env:"STORAGE_HOST_PATH,default="`
	PFSEtcdPrefix              string `env:"PFS_ETCD_PREFIX,default=pachyderm_pfs"`
	KubeAddress                string `env:"KUBERNETES_PORT_443_TCP_ADDR,required"`
	Init                       bool   `env:"INIT,default=false"`
	WorkerImage                string `env:"WORKER_IMAGE,default="`
	WorkerSidecarImage         string `env:"WORKER_SIDECAR_IMAGE,default="`
	WorkerImagePullPolicy      string `env:"WORKER_IMAGE_PULL_POLICY,default="`
	IAMRole                    string `env:"IAM_ROLE,default="`
	ImagePullSecret            string `env:"IMAGE_PULL_SECRET,default="`
	NoExposeDockerSocket       bool   `env:"NO_EXPOSE_DOCKER_SOCKET,default=false"`
	MemoryRequest              string `env:"PACHD_MEMORY_REQUEST,default=1T"`
	WorkerUsesRoot             bool   `env:"WORKER_USES_ROOT,default=true"`
	RequireCriticalServersOnly bool   `env:"REQUIRE_CRITICAL_SERVERS_ONLY,default=false"`
	// TODO: Merge this with the worker specific pod name (PPS_POD_NAME) into a global configuration pod name.
	PachdPodName string `env:"PACHD_POD_NAME,required"`
}

// StorageConfiguration contains the storage configuration.
type StorageConfiguration struct {
	StorageMemoryThreshold         int64  `env:"STORAGE_MEMORY_THRESHOLD"`
	StorageShardThreshold          int64  `env:"STORAGE_SHARD_THRESHOLD"`
	StorageLevelFactor             int64  `env:"STORAGE_LEVEL_FACTOR"`
	StorageUploadConcurrencyLimit  int    `env:"STORAGE_UPLOAD_CONCURRENCY_LIMIT,default=100"`
	StoragePutFileConcurrencyLimit int    `env:"STORAGE_PUT_FILE_CONCURRENCY_LIMIT,default=100"`
	StorageGCPolling               string `env:"STORAGE_GC_POLLING"`
	StorageGCTimeout               string `env:"STORAGE_GC_TIMEOUT"`
	StorageCompactionMaxFanIn      int    `env:"STORAGE_COMPACTION_MAX_FANIN,default=10"`
	StorageFileSetsMaxOpen         int    `env:"STORAGE_FILESETS_MAX_OPEN,default=50"`
	StorageDiskCacheSize           int    `env:"STORAGE_DISK_CACHE_SIZE,default=100"`
	StorageMemoryCacheSize         int    `env:"STORAGE_MEMORY_CACHE_SIZE,default=100"`
}

// WorkerFullConfiguration contains the full worker configuration.
type WorkerFullConfiguration struct {
	GlobalConfiguration
	WorkerSpecificConfiguration
}

// WorkerSpecificConfiguration contains the worker specific configuration.
type WorkerSpecificConfiguration struct {
	// Worker gets its own IP here, via the k8s downward API. It then writes that
	// IP back to etcd so that pachd can discover it
	PPSWorkerIP string `env:"PPS_WORKER_IP,required"`
	// The name of this pod
	PodName string `env:"PPS_POD_NAME,required"`
}

// FeatureFlags contains the configuration for feature flags.  XXX: if you're
// adding a new feature flag then you need to make sure it gets propagated to
// the workers and their sidecars, this should be done in:
// src/server/pps/server/worker_rc.go in the workerPodSpec func.
type FeatureFlags struct {
	DisableCommitProgressCounter bool `env:"DISABLE_COMMIT_PROGRESS_COUNTER,default=false"`
	LokiLogging                  bool `env:"LOKI_LOGGING,default=false"`
	IdentityServerEnabled        bool `env:"IDENTITY_SERVER_ENABLED,default=false"`
}

// NewConfiguration creates a generic configuration from a specific type of configuration.
func NewConfiguration(config interface{}) *Configuration {
	configuration := &Configuration{}
	switch v := config.(type) {
	case *GlobalConfiguration:
		configuration.GlobalConfiguration = v
		return configuration
	case *PachdFullConfiguration:
		configuration.GlobalConfiguration = &v.GlobalConfiguration
		configuration.PachdSpecificConfiguration = &v.PachdSpecificConfiguration
		return configuration
	case *WorkerFullConfiguration:
		configuration.GlobalConfiguration = &v.GlobalConfiguration
		configuration.WorkerSpecificConfiguration = &v.WorkerSpecificConfiguration
		return configuration
	default:
		return nil
	}
}
<commit_msg>Remove unused env vars (#6391)<commit_after>package serviceenv

// Configuration is the generic configuration structure used to access configuration fields.
type Configuration struct {
	*GlobalConfiguration
	*PachdSpecificConfiguration
	*WorkerSpecificConfiguration
}

// GlobalConfiguration contains the global configuration.
type GlobalConfiguration struct {
	FeatureFlags
	EtcdHost            string `env:"ETCD_SERVICE_HOST,required"`
	EtcdPort            string `env:"ETCD_SERVICE_PORT,required"`
	PPSWorkerPort       uint16 `env:"PPS_WORKER_GRPC_PORT,default=1080"`
	Port                uint16 `env:"PORT,default=1650"`
	PeerPort            uint16 `env:"PEER_PORT,default=1653"`
	S3GatewayPort       uint16 `env:"S3GATEWAY_PORT,default=1600"`
	PPSEtcdPrefix       string `env:"PPS_ETCD_PREFIX,default=pachyderm_pps"`
	Namespace           string `env:"PACH_NAMESPACE,default=default"`
	StorageRoot         string `env:"PACH_ROOT,default=/pach"`
	GCPercent           int    `env:"GC_PERCENT,default=50"`
	LokiHost            string `env:"LOKI_SERVICE_HOST"`
	LokiPort            string `env:"LOKI_SERVICE_PORT"`
	OidcPort            uint16 `env:"OIDC_PORT,default=1657"`
	PostgresServiceHost string `env:"POSTGRES_SERVICE_HOST"`
	PostgresServicePort int    `env:"POSTGRES_SERVICE_PORT"`
	PostgresServiceSSL  string `env:"POSTGRES_SERVICE_SSL,default=disable"`
	PostgresDBName      string `env:"POSTGRES_DATABASE_NAME"`

	EtcdPrefix           string `env:"ETCD_PREFIX,default="`
	DeploymentID         string `env:"CLUSTER_DEPLOYMENT_ID,default="`
	LogLevel             string `env:"LOG_LEVEL,default=info"`
	EnterpriseEtcdPrefix string `env:"PACHYDERM_ENTERPRISE_ETCD_PREFIX,default=pachyderm_enterprise"`
	Metrics              bool   `env:"METRICS,default=true"`
	MetricsEndpoint      string `env:"METRICS_ENDPOINT,default="`

	// SessionDurationMinutes it how long auth tokens are valid for, defaults to 30 days (30 * 24 * 60)
	SessionDurationMinutes int `env:"SESSION_DURATION_MINUTES,default=43200"`

	IdentityServerDatabase string `env:"IDENTITY_SERVER_DATABASE,default=dex"`
	IdentityServerUser     string `env:"IDENTITY_SERVER_USER,default=postgres"`
	IdentityServerPassword string `env:"IDENTITY_SERVER_PASSWORD"`

	// PPSSpecCommitID and PPSPipelineName are only set for workers and sidecar
	// pachd instances. Because both pachd and worker need to know the spec commit
	// (the worker so that it can avoid jobs for other versions of the same pipelines
	// and the sidecar so that it can serve the S3 gateway) it's stored in the
	// GlobalConfiguration, but it isn't set in a cluster's main pachd containers.
	PPSSpecCommitID string `env:"PPS_SPEC_COMMIT"`
	// The name of the pipeline that this worker belongs to
	PPSPipelineName string `env:"PPS_PIPELINE_NAME"`
}

// PachdFullConfiguration contains the full pachd configuration.
type PachdFullConfiguration struct {
	GlobalConfiguration
	PachdSpecificConfiguration
}

// PachdSpecificConfiguration contains the pachd specific configuration.
type PachdSpecificConfiguration struct {
	StorageConfiguration
	StorageBackend             string `env:"STORAGE_BACKEND,required"`
	StorageHostPath            string `env:"STORAGE_HOST_PATH,default="`
	PFSEtcdPrefix              string `env:"PFS_ETCD_PREFIX,default=pachyderm_pfs"`
	KubeAddress                string `env:"KUBERNETES_PORT_443_TCP_ADDR,required"`
	Init                       bool   `env:"INIT,default=false"`
	WorkerImage                string `env:"WORKER_IMAGE,default="`
	WorkerSidecarImage         string `env:"WORKER_SIDECAR_IMAGE,default="`
	WorkerImagePullPolicy      string `env:"WORKER_IMAGE_PULL_POLICY,default="`
	IAMRole                    string `env:"IAM_ROLE,default="`
	ImagePullSecret            string `env:"IMAGE_PULL_SECRET,default="`
	NoExposeDockerSocket       bool   `env:"NO_EXPOSE_DOCKER_SOCKET,default=false"`
	MemoryRequest              string `env:"PACHD_MEMORY_REQUEST,default=1T"`
	WorkerUsesRoot             bool   `env:"WORKER_USES_ROOT,default=true"`
	RequireCriticalServersOnly bool   `env:"REQUIRE_CRITICAL_SERVERS_ONLY,default=false"`
	// TODO: Merge this with the worker specific pod name (PPS_POD_NAME) into a global configuration pod name.
	PachdPodName string `env:"PACHD_POD_NAME,required"`
}

// StorageConfiguration contains the storage configuration.
type StorageConfiguration struct {
	StorageMemoryThreshold         int64  `env:"STORAGE_MEMORY_THRESHOLD"`
	StorageShardThreshold          int64  `env:"STORAGE_SHARD_THRESHOLD"`
	StorageLevelFactor             int64  `env:"STORAGE_LEVEL_FACTOR"`
	StorageUploadConcurrencyLimit  int    `env:"STORAGE_UPLOAD_CONCURRENCY_LIMIT,default=100"`
	StoragePutFileConcurrencyLimit int    `env:"STORAGE_PUT_FILE_CONCURRENCY_LIMIT,default=100"`
	StorageGCPolling               string `env:"STORAGE_GC_POLLING"`
	StorageGCTimeout               string `env:"STORAGE_GC_TIMEOUT"`
	StorageCompactionMaxFanIn      int    `env:"STORAGE_COMPACTION_MAX_FANIN,default=10"`
	StorageFileSetsMaxOpen         int    `env:"STORAGE_FILESETS_MAX_OPEN,default=50"`
	StorageDiskCacheSize           int    `env:"STORAGE_DISK_CACHE_SIZE,default=100"`
	StorageMemoryCacheSize         int    `env:"STORAGE_MEMORY_CACHE_SIZE,default=100"`
}

// WorkerFullConfiguration contains the full worker configuration.
type WorkerFullConfiguration struct {
	GlobalConfiguration
	WorkerSpecificConfiguration
}

// WorkerSpecificConfiguration contains the worker specific configuration.
type WorkerSpecificConfiguration struct {
	// Worker gets its own IP here, via the k8s downward API. It then writes that
	// IP back to etcd so that pachd can discover it
	PPSWorkerIP string `env:"PPS_WORKER_IP,required"`
	// The name of this pod
	PodName string `env:"PPS_POD_NAME,required"`
}

// FeatureFlags contains the configuration for feature flags.  XXX: if you're
// adding a new feature flag then you need to make sure it gets propagated to
// the workers and their sidecars, this should be done in:
// src/server/pps/server/worker_rc.go in the workerPodSpec func.
type FeatureFlags struct {
	DisableCommitProgressCounter bool `env:"DISABLE_COMMIT_PROGRESS_COUNTER,default=false"`
	LokiLogging                  bool `env:"LOKI_LOGGING,default=false"`
	IdentityServerEnabled        bool `env:"IDENTITY_SERVER_ENABLED,default=false"`
}

// NewConfiguration creates a generic configuration from a specific type of configuration.
func NewConfiguration(config interface{}) *Configuration {
	configuration := &Configuration{}
	switch v := config.(type) {
	case *GlobalConfiguration:
		configuration.GlobalConfiguration = v
		return configuration
	case *PachdFullConfiguration:
		configuration.GlobalConfiguration = &v.GlobalConfiguration
		configuration.PachdSpecificConfiguration = &v.PachdSpecificConfiguration
		return configuration
	case *WorkerFullConfiguration:
		configuration.GlobalConfiguration = &v.GlobalConfiguration
		configuration.WorkerSpecificConfiguration = &v.WorkerSpecificConfiguration
		return configuration
	default:
		return nil
	}
}
<|endoftext|>


<commit_before>package solution

import (
	"log"
	"math"

	"github.com/turing-complete/laboratory/src/internal/config"
	"github.com/turing-complete/laboratory/src/internal/quantity"

	interpolation "github.com/ready-steady/adapt/algorithm/external"
	algorithm "github.com/ready-steady/adapt/algorithm/hybrid"
)

type strategy struct {
	algorithm.Strategy

	nmax uint

	ns uint
	nn uint

	active []uint
}

func newStrategy(target, reference quantity.Quantity, guide algorithm.Guide,
	config *config.Solution) *strategy {

	ni, no := target.Dimensions()
	return &strategy{
		Strategy: *algorithm.NewStrategy(ni, no, guide, config.MinLevel,
			config.MaxLevel, config.LocalError, config.TotalError),

		nmax: config.MaxEvaluations,
	}
}

func (self *strategy) Done(state *interpolation.State, surrogate *interpolation.Surrogate) bool {
	if self.ns == 0 {
		log.Printf("%5s %15s %15s\n", "Step", "New Nodes", "Old Nodes")
	}

	if self.Strategy.Done(state, surrogate) {
		return true
	}

	nn := uint(len(state.Indices)) / surrogate.Inputs
	if self.nn+nn > self.nmax {
		return true
	}

	log.Printf("%5d %15d %15d\n", self.ns, nn, self.nn)

	self.nn += nn
	self.ns += 1
	self.active = append(self.active, nn)

	return false
}

func (self *strategy) Score(element *interpolation.Element) float64 {
	return maxAbsolute(element.Surplus) * element.Volume
}

func maxAbsolute(data []float64) (value float64) {
	for i, n := uint(0), uint(len(data)); i < n; i++ {
		value = math.Max(value, math.Abs(data[i]))
	}
	return
}
<commit_msg>i/solution: print the current level<commit_after>package solution

import (
	"log"
	"math"

	"github.com/turing-complete/laboratory/src/internal/config"
	"github.com/turing-complete/laboratory/src/internal/quantity"

	interpolation "github.com/ready-steady/adapt/algorithm/external"
	algorithm "github.com/ready-steady/adapt/algorithm/hybrid"
)

type strategy struct {
	algorithm.Strategy

	nmax uint

	ns uint
	nn uint

	active []uint
}

func newStrategy(target, reference quantity.Quantity, guide algorithm.Guide,
	config *config.Solution) *strategy {

	ni, no := target.Dimensions()
	return &strategy{
		Strategy: *algorithm.NewStrategy(ni, no, guide, config.MinLevel,
			config.MaxLevel, config.LocalError, config.TotalError),

		target:    target,
		reference: reference,

		nmax: config.MaxEvaluations,
	}
}

func (self *strategy) Done(state *interpolation.State, surrogate *interpolation.Surrogate) bool {
	if self.ns == 0 {
		log.Printf("%5s %15s %15s %15s\n", "Step", "Old Nodes", "New Nodes", "New Level")
	}

	if self.Strategy.Done(state, surrogate) {
		return true
	}

	ni := surrogate.Inputs
	nn := uint(len(state.Indices)) / ni
	if self.nn+nn > self.nmax {
		return true
	}

	level := maxLevel(state.Lindices, ni)

	log.Printf("%5d %15d %15d %15d\n", self.ns, self.nn, nn, level)

	self.ns += 1
	self.nn += nn
	self.active = append(self.active, nn)

	return false
}

func (self *strategy) Score(element *interpolation.Element) float64 {
	return maxAbsolute(element.Surplus) * element.Volume
}

func maxAbsolute(data []float64) (value float64) {
	for i, n := uint(0), uint(len(data)); i < n; i++ {
		value = math.Max(value, math.Abs(data[i]))
	}
	return
}

func maxLevel(lindices []uint64, ni uint) (level uint64) {
	nn := uint(len(lindices)) / ni
	for i := uint(0); i < nn; i++ {
		l := uint64(0)
		for j := uint(0); j < ni; j++ {
			l += lindices[i*ni+j]
		}
		if l > level {
			level = l
		}
	}
	return
}
<|endoftext|>


<commit_before>package calendar

import (
	"time"
)

// these change every year
var (
	Day_SchoolStart, _    = time.Parse("2006-01-02", "2018-09-12")
	Day_Candlelighting, _ = time.Parse("2006-01-02", "2018-12-21")
	Day_ExamRelief, _     = time.Parse("2006-01-02", "2019-01-25")
	Day_SchoolEnd, _      = time.Parse("2006-01-02", "2019-06-06")

	// SpecialSchedule_HS_Candlelighting = []CalendarSpecialScheduleItem{
	// 	CalendarSpecialScheduleItem{"C", "", 29400, 31500},
	// 	CalendarSpecialScheduleItem{"D", "", 31800, 33900},
	// 	CalendarSpecialScheduleItem{"H", "", 34200, 36300},
	// 	CalendarSpecialScheduleItem{"G", "", 36600, 38700},
	// 	CalendarSpecialScheduleItem{"", "Long House", 39000, 41100},
	// 	CalendarSpecialScheduleItem{"", "Candlelighting ceremony", 41400, 43200},
	// }

	// import ranges
	// these should be ranges with 4 fridays in a row and the first week having no off days
	Term1_Import_Start = time.Date(2018, time.September, 24, 0, 0, 0, 0, time.UTC)
	Term1_Import_End   = time.Date(2018, time.October, 20, 0, 0, 0, 0, time.UTC)

	Term1_Import_DayOffset_Friday1 = ((7 * 3) + 4)
	Term1_Import_DayOffset_Friday2 = 4
	Term1_Import_DayOffset_Friday3 = ((7 * 1) + 4)
	Term1_Import_DayOffset_Friday4 = ((7 * 2) + 4)

	Term2_Import_Start = time.Date(2019, time.January, 28, 0, 0, 0, 0, time.UTC)
	Term2_Import_End   = time.Date(2019, time.February, 23, 0, 0, 0, 0, time.UTC)

	Term2_Import_DayOffset_Friday1 = ((7 * 3) + 4)
	Term2_Import_DayOffset_Friday2 = 4
	Term2_Import_DayOffset_Friday3 = ((7 * 1) + 4)
	Term2_Import_DayOffset_Friday4 = ((7 * 2) + 4)

	// HACK: hard-coded friday list because we can't get the fridays from the schedule because some MS teacher schedules don't have the numbers for some reason
	ScheduleFridayList = map[string]int{
		"2018-09-14": 1,
		"2018-09-21": 2,
		"2018-09-28": 3,
		"2018-10-05": 4,
		"2018-10-12": 1,
		"2018-10-19": 2,
		"2018-10-26": 3,
		"2018-11-02": 4,
		"2018-11-09": 1,
		"2018-11-16": 2,
		"2018-11-30": 3,
		"2018-12-07": 4,
		"2018-12-14": 1,
		"2019-01-11": 3,
		"2019-01-18": 4,
		"2019-01-25": 1,
		"2019-02-01": 2,
		"2019-02-08": 3,
		"2019-02-15": 4,
		"2019-02-22": 1,
		"2019-03-01": 2,
		"2019-03-08": 3,
		"2019-03-15": 4,
		"2019-04-05": 1,
		"2019-04-12": 2,
		"2019-04-26": 3,
		"2019-05-03": 4,
		"2019-05-10": 1,
		"2019-05-17": 2,
		"2019-05-24": 3,
		"2019-05-31": 4,
	}

	AssemblyTypeList = map[string]AssemblyType{
		"2018-09-13": AssemblyType_Assembly,
		"2018-09-20": AssemblyType_Assembly,
		"2018-09-27": AssemblyType_Lab,
		"2018-10-04": AssemblyType_Assembly,
		"2018-10-11": AssemblyType_Lab,
		"2018-10-18": AssemblyType_Assembly,
		"2018-10-25": AssemblyType_LongHouse,
		"2018-11-01": AssemblyType_Assembly,
		"2018-11-08": AssemblyType_Lab,
		"2018-11-15": AssemblyType_Assembly,
		"2018-11-29": AssemblyType_Lab,
		"2018-12-06": AssemblyType_Assembly,
		"2018-12-13": AssemblyType_LongHouse,
		"2018-12-20": AssemblyType_Assembly,
		"2019-01-10": AssemblyType_Lab,
		"2019-01-31": AssemblyType_Assembly,
		"2019-02-07": AssemblyType_Lab,
		"2019-02-14": AssemblyType_Assembly,
		"2019-02-21": AssemblyType_LongHouse,
		"2019-02-28": AssemblyType_Assembly,
		"2019-03-07": AssemblyType_Lab,
		"2019-03-14": AssemblyType_Assembly,
		"2019-04-04": AssemblyType_Lab,
		"2019-04-11": AssemblyType_Assembly,
		"2019-04-18": AssemblyType_Assembly,
		"2019-04-25": AssemblyType_LongHouse,
		"2019-05-02": AssemblyType_Assembly,
		"2019-05-09": AssemblyType_Lab,
		"2019-05-16": AssemblyType_Assembly,
		"2019-05-23": AssemblyType_Assembly,
	}

	SpecialAssessmentList = map[int]*SpecialAssessmentInfo{}
	SpecialAssessmentDays = map[string]SpecialAssessmentType{}
)

const (
	AnnouncementType_Text       = 0 // just informative
	AnnouncementType_FullOff    = 1 // no classes at all
	AnnouncementType_BreakStart = 2 // start of a break (inclusive of that day!)
	AnnouncementType_BreakEnd   = 3 // end of a break (exclusive of that day!)
)

const (
	SpecialAssessmentType_Unknown  SpecialAssessmentType = 0
	SpecialAssessmentType_English                        = 1
	SpecialAssessmentType_History                        = 2
	SpecialAssessmentType_Math                           = 3
	SpecialAssessmentType_Science                        = 4
	SpecialAssessmentType_Language                       = 5
)

// An AssemblyType describes what happens for assembly on a given week.
type AssemblyType int

const (
	AssemblyType_Assembly AssemblyType = iota
	AssemblyType_LongHouse
	AssemblyType_Lab
)

func InitCalendar() {
	// special assessments
	// no special assessments at this time
}
<commit_msg>update assembly schedule due to postponed assembly<commit_after>package calendar

import (
	"time"
)

// these change every year
var (
	Day_SchoolStart, _    = time.Parse("2006-01-02", "2018-09-12")
	Day_Candlelighting, _ = time.Parse("2006-01-02", "2018-12-21")
	Day_ExamRelief, _     = time.Parse("2006-01-02", "2019-01-25")
	Day_SchoolEnd, _      = time.Parse("2006-01-02", "2019-06-06")

	// SpecialSchedule_HS_Candlelighting = []CalendarSpecialScheduleItem{
	// 	CalendarSpecialScheduleItem{"C", "", 29400, 31500},
	// 	CalendarSpecialScheduleItem{"D", "", 31800, 33900},
	// 	CalendarSpecialScheduleItem{"H", "", 34200, 36300},
	// 	CalendarSpecialScheduleItem{"G", "", 36600, 38700},
	// 	CalendarSpecialScheduleItem{"", "Long House", 39000, 41100},
	// 	CalendarSpecialScheduleItem{"", "Candlelighting ceremony", 41400, 43200},
	// }

	// import ranges
	// these should be ranges with 4 fridays in a row and the first week having no off days
	Term1_Import_Start = time.Date(2018, time.September, 24, 0, 0, 0, 0, time.UTC)
	Term1_Import_End   = time.Date(2018, time.October, 20, 0, 0, 0, 0, time.UTC)

	Term1_Import_DayOffset_Friday1 = ((7 * 3) + 4)
	Term1_Import_DayOffset_Friday2 = 4
	Term1_Import_DayOffset_Friday3 = ((7 * 1) + 4)
	Term1_Import_DayOffset_Friday4 = ((7 * 2) + 4)

	Term2_Import_Start = time.Date(2019, time.January, 28, 0, 0, 0, 0, time.UTC)
	Term2_Import_End   = time.Date(2019, time.February, 23, 0, 0, 0, 0, time.UTC)

	Term2_Import_DayOffset_Friday1 = ((7 * 3) + 4)
	Term2_Import_DayOffset_Friday2 = 4
	Term2_Import_DayOffset_Friday3 = ((7 * 1) + 4)
	Term2_Import_DayOffset_Friday4 = ((7 * 2) + 4)

	// HACK: hard-coded friday list because we can't get the fridays from the schedule because some MS teacher schedules don't have the numbers for some reason
	ScheduleFridayList = map[string]int{
		"2018-09-14": 1,
		"2018-09-21": 2,
		"2018-09-28": 3,
		"2018-10-05": 4,
		"2018-10-12": 1,
		"2018-10-19": 2,
		"2018-10-26": 3,
		"2018-11-02": 4,
		"2018-11-09": 1,
		"2018-11-16": 2,
		"2018-11-30": 3,
		"2018-12-07": 4,
		"2018-12-14": 1,
		"2019-01-11": 3,
		"2019-01-18": 4,
		"2019-01-25": 1,
		"2019-02-01": 2,
		"2019-02-08": 3,
		"2019-02-15": 4,
		"2019-02-22": 1,
		"2019-03-01": 2,
		"2019-03-08": 3,
		"2019-03-15": 4,
		"2019-04-05": 1,
		"2019-04-12": 2,
		"2019-04-26": 3,
		"2019-05-03": 4,
		"2019-05-10": 1,
		"2019-05-17": 2,
		"2019-05-24": 3,
		"2019-05-31": 4,
	}

	AssemblyTypeList = map[string]AssemblyType{
		"2018-09-13": AssemblyType_Assembly,
		"2018-09-20": AssemblyType_Assembly,
		"2018-09-27": AssemblyType_LongHouse,
		"2018-10-04": AssemblyType_Assembly,
		"2018-10-11": AssemblyType_Lab,
		"2018-10-18": AssemblyType_Assembly,
		"2018-10-25": AssemblyType_LongHouse,
		"2018-11-01": AssemblyType_Assembly,
		"2018-11-08": AssemblyType_Lab,
		"2018-11-15": AssemblyType_Assembly,
		"2018-11-29": AssemblyType_Lab,
		"2018-12-06": AssemblyType_Assembly,
		"2018-12-13": AssemblyType_LongHouse,
		"2018-12-20": AssemblyType_Assembly,
		"2019-01-10": AssemblyType_Lab,
		"2019-01-31": AssemblyType_Assembly,
		"2019-02-07": AssemblyType_Lab,
		"2019-02-14": AssemblyType_Assembly,
		"2019-02-21": AssemblyType_LongHouse,
		"2019-02-28": AssemblyType_Assembly,
		"2019-03-07": AssemblyType_Lab,
		"2019-03-14": AssemblyType_Assembly,
		"2019-04-04": AssemblyType_Lab,
		"2019-04-11": AssemblyType_Assembly,
		"2019-04-18": AssemblyType_Assembly,
		"2019-04-25": AssemblyType_LongHouse,
		"2019-05-02": AssemblyType_Assembly,
		"2019-05-09": AssemblyType_Lab,
		"2019-05-16": AssemblyType_Assembly,
		"2019-05-23": AssemblyType_Assembly,
	}

	SpecialAssessmentList = map[int]*SpecialAssessmentInfo{}
	SpecialAssessmentDays = map[string]SpecialAssessmentType{}
)

const (
	AnnouncementType_Text       = 0 // just informative
	AnnouncementType_FullOff    = 1 // no classes at all
	AnnouncementType_BreakStart = 2 // start of a break (inclusive of that day!)
	AnnouncementType_BreakEnd   = 3 // end of a break (exclusive of that day!)
)

const (
	SpecialAssessmentType_Unknown  SpecialAssessmentType = 0
	SpecialAssessmentType_English                        = 1
	SpecialAssessmentType_History                        = 2
	SpecialAssessmentType_Math                           = 3
	SpecialAssessmentType_Science                        = 4
	SpecialAssessmentType_Language                       = 5
)

// An AssemblyType describes what happens for assembly on a given week.
type AssemblyType int

const (
	AssemblyType_Assembly AssemblyType = iota
	AssemblyType_LongHouse
	AssemblyType_Lab
)

func InitCalendar() {
	// special assessments
	// no special assessments at this time
}
<|endoftext|>


<commit_before>package xmlpull

// xgo/xml/xmlpull/minimalDoc_test.go

import (
	"fmt"
	xr "github.com/jddixon/rnglib_go"
	. "gopkg.in/check.v1"
	"io"
	"strings"
)

var _ = fmt.Print

const (
	XML_DECL     = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
	DOCTYPE_DECL = "<!DOCTYPE document PUBLIC \"-//APACHE//DTD Documentation V2.0//EN\" \"http://forrest.apache.org/dtd/document-v20.dtd\">"
	PROLOG_MISC  = "<!-- this is a comment in the prolog -->\n"
	EPILOG_MISC  = "<!-- this is a comment in the epilog -->\n"
	EMPTY_ELM    = "<root/>"
)

func (s *XLSuite) doInitialParse(c *C, input string) (p *Parser) {

	// DEBUG
	fmt.Printf("PARSING: '%s'\n", input)
	// END
	rd := strings.NewReader(input)
	p, err := NewNewParser(rd)
	c.Assert(err, IsNil)
	c.Assert(p, NotNil)
	c.Assert(p.state, Equals, PRE_START_DOC)

	event, err := p.NextToken()
	c.Assert(err, IsNil)
	c.Assert(event, Equals, START_DOCUMENT)
	c.Assert(p.state, Equals, START_STATE)
	return
}

func (s *XLSuite) doParseXmlDecl(c *C, input string) (
	p *Parser, event PullEvent) {

	p = s.doInitialParse(c, input)

	event, err := p.NextToken()
	c.Assert(err, IsNil)

	c.Assert(p.xmlVersion, Equals, "1.0")
	c.Assert(p.xmlEncoding, Equals, "UTF-8")

	return
}

func (s *XLSuite) doParseXmlDeclWithMisc(c *C, input string,
	misc1 []*MiscItem) (p *Parser, event PullEvent) {

	p = s.doInitialParse(c, input)

	//////////////////////////////////////////////////////////
	// THIS IS OUR OWN LOCAL COPY OF THE EVENT, NOT p.curEvent
	//////////////////////////////////////////////////////////
	event, err := p.NextToken()
	c.Assert(err, IsNil)

	c.Assert(p.xmlVersion, Equals, "1.0")
	c.Assert(p.xmlEncoding, Equals, "UTF-8")

	for i := 0; i < len(misc1); i++ {
		// DEBUG
		fmt.Printf("Misc[%d]: event is %s\n",
			i, PULL_EVENT_NAMES[event])
		// END
		misc := misc1[i]
		t := misc._type
		if event != eventForMiscType[t] {
			fmt.Printf(
				"expected event %s for misc type %s but event is %s\n",
				PULL_EVENT_NAMES[eventForMiscType[t]],
				MiscTypeNames[t],
				PULL_EVENT_NAMES[event])
		}
		c.Assert(event, Equals, eventForMiscType[t])
		switch t {
		case MISC_COMMENT:
			c.Assert(string(p.commentChars), Equals, string(misc.body))
		case MISC_PI:
			c.Assert(string(p.piChars), Equals, string(misc.body))
		case MISC_S:
			c.Assert(string(p.text), Equals, string(misc.body))
		}
		event, err = p.NextToken()
	}
	return
}

// Parse a sequence: XmlDecl Misc* (doctypedecl Misc*) EmptyElement Misc*
func (s *XLSuite) doParseBothDecl(c *C, input string) (
	p *Parser, event PullEvent) {

	// DEBUG
	fmt.Printf("doParseBothDecl: INPUT: %s\n", input)
	// END

	var err error
	p, event = s.doParseXmlDecl(c, input)

	// we have seen the XmlDecl; now allow zero or more Misc but
	// requuire doctypedecl
	for event != DOCDECL {
		if event == IGNORABLE_WHITESPACE || event == PROCESSING_INSTRUCTION ||
			event == COMMENT {

			event, err = p.NextToken()
		} else {
			fmt.Printf("expected DOCDECL but got %s\n", PULL_EVENT_NAMES[event])
		}
	}
	c.Assert(event, Equals, DOCDECL)

	event, err = p.NextToken()
	c.Assert(err, IsNil)

	// Allow zero or more Misc but require the EmptyElement
	for event != START_TAG {
		if event == IGNORABLE_WHITESPACE || event == PROCESSING_INSTRUCTION ||
			event == COMMENT {

			event, err = p.NextToken()
		} else {
			fmt.Printf("expected START_TAG but got %s\n", PULL_EVENT_NAMES[event])
			break // XXX SHOULD FAIL
		}
	}
	c.Assert(err, IsNil)
	c.Assert(event, Equals, START_TAG)

	event, err = p.NextToken()
	// DEBUG
	fmt.Printf("DoParseBothDecl: NextToken => event %d, err %v\n",
		event, err)
	// END
	c.Assert(err == nil || err == io.EOF, Equals, true)
	fmt.Printf("err: %v\n", err)
	c.Assert(event, Equals, END_DOCUMENT)
	return
}

func (s *XLSuite) TestParseEmptyElm(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_EMPTY_ELM")
	}
	s.doInitialParse(c, EMPTY_ELM)
}

func (s *XLSuite) TestParseXmlDeclPlusElm(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_XML_DECL_PLUS_ELM")
	}
	s.doParseXmlDecl(c, XML_DECL+EMPTY_ELM)
}

// Parse an XmlDecl followed by an (empty) element followed by Misc
func (s *XLSuite) TestParseXmlDeclPlusElmPlusMisc(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_XML_DECL_PLUS_ELM_PLUS_MISC")
	}
	rng := xr.MakeSimpleRNG()
	misc1 := s.createMiscItems(rng) // a small, possibly empty, slice
	miscN := s.createMiscItems(rng) // a small, possibly empty, slice
	s.doParseXmlDeclWithMisc(c, XML_DECL+s.textFromMISlice(misc1)+
		EMPTY_ELM+s.textFromMISlice(miscN), misc1)
}

func (s *XLSuite) TestParseBothDeclPlusElm(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_BOTH_DECL_PLUS_ELM")
	}
	s.doParseBothDecl(c, XML_DECL+DOCTYPE_DECL+EMPTY_ELM)
}

// Parse an XmlDecl followed a DocDecl followed by an (empty) element followed
// by Misc
// [1]  document ::= prolog element Misc*
// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
//
func (s *XLSuite) TestParseBothDeclPlusElmPlusMisc(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_BOTH_DECL_PLUS_ELM_PLUS_MISC")
	}
	rng := xr.MakeSimpleRNG()
	misc1 := s.createMiscItems(rng) // a small, possibly empty, slice
	misc2 := s.createMiscItems(rng) // a small, possibly empty, slice
	miscN := s.createMiscItems(rng) // a small, possibly empty, slice
	s.doParseBothDecl(c,
		XML_DECL+s.textFromMISlice(misc1)+
			DOCTYPE_DECL+s.textFromMISlice(misc2)+
			EMPTY_ELM+s.textFromMISlice(miscN))
}

// Simple test that constants and their string representations agree.
//
func (s *XLSuite) TestParserConst(c *C) {
	c.Assert(PARSER_STATE_NAMES[PRE_START_DOC], Equals, "PRE_START_DOC")
	c.Assert(PARSER_STATE_NAMES[START_ROOT_SEEN], Equals, "START_ROOT_SEEN")
	c.Assert(PARSER_STATE_NAMES[PAST_END_DOC], Equals, "PAST_END_DOC")
}
<commit_msg>proj: COLLECTING_EPILOG tests OK<commit_after>package xmlpull

// xgo/xml/xmlpull/minimalDoc_test.go

import (
	"fmt"
	xr "github.com/jddixon/rnglib_go"
	. "gopkg.in/check.v1"
	"io"
	"strings"
)

var _ = fmt.Print

const (
	XML_DECL     = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
	DOCTYPE_DECL = "<!DOCTYPE document PUBLIC \"-//APACHE//DTD Documentation V2.0//EN\" \"http://forrest.apache.org/dtd/document-v20.dtd\">"
	PROLOG_MISC  = "<!-- this is a comment in the prolog -->\n"
	EPILOG_MISC  = "<!-- this is a comment in the epilog -->\n"
	EMPTY_ELM    = "<root/>"
)

func (s *XLSuite) doInitialParse(c *C, input string) (p *Parser) {

	// DEBUG
	fmt.Printf("PARSING: '%s'\n", input)
	// END
	rd := strings.NewReader(input)
	p, err := NewNewParser(rd)
	c.Assert(err, IsNil)
	c.Assert(p, NotNil)
	c.Assert(p.state, Equals, PRE_START_DOC)

	event, err := p.NextToken()
	c.Assert(err, IsNil)
	c.Assert(event, Equals, START_DOCUMENT)
	c.Assert(p.state, Equals, START_STATE)
	return
}

func (s *XLSuite) doParseXmlDecl(c *C, input string) (
	p *Parser, event PullEvent) {

	p = s.doInitialParse(c, input)

	event, err := p.NextToken()
	c.Assert(err, IsNil)

	c.Assert(p.xmlVersion, Equals, "1.0")
	c.Assert(p.xmlEncoding, Equals, "UTF-8")

	return
}

func (s *XLSuite) doParseXmlDeclWithMisc(c *C, input string,
	misc1 []*MiscItem) (p *Parser, event PullEvent) {

	p = s.doInitialParse(c, input)

	//////////////////////////////////////////////////////////
	// THIS IS OUR OWN LOCAL COPY OF THE EVENT, NOT p.curEvent
	//////////////////////////////////////////////////////////
	event, err := p.NextToken()
	c.Assert(err, IsNil)

	c.Assert(p.xmlVersion, Equals, "1.0")
	c.Assert(p.xmlEncoding, Equals, "UTF-8")

	for i := 0; i < len(misc1); i++ {
		// DEBUG
		fmt.Printf("Misc[%d]: event is %s\n",
			i, PULL_EVENT_NAMES[event])
		// END
		misc := misc1[i]
		t := misc._type
		if event != eventForMiscType[t] {
			fmt.Printf(
				"expected event %s for misc type %s but event is %s\n",
				PULL_EVENT_NAMES[eventForMiscType[t]],
				MiscTypeNames[t],
				PULL_EVENT_NAMES[event])
		}
		c.Assert(event, Equals, eventForMiscType[t])
		switch t {
		case MISC_COMMENT:
			c.Assert(string(p.commentChars), Equals, string(misc.body))
		case MISC_PI:
			c.Assert(string(p.piChars), Equals, string(misc.body))
		case MISC_S:
			c.Assert(string(p.text), Equals, string(misc.body))
		}
		event, err = p.NextToken()
	}
	return
}

// Parse a sequence: XmlDecl Misc* (doctypedecl Misc*) EmptyElement Misc*
func (s *XLSuite) doParseBothDecl(c *C, input string) (
	p *Parser, event PullEvent) {

	// DEBUG
	fmt.Printf("doParseBothDecl: INPUT: %s\n", input)
	// END

	var err error
	p, event = s.doParseXmlDecl(c, input)

	// we have seen the XmlDecl; now allow zero or more Misc but
	// requuire doctypedecl
	for event != DOCDECL {
		if event == IGNORABLE_WHITESPACE || event == PROCESSING_INSTRUCTION ||
			event == COMMENT {

			event, err = p.NextToken()
		} else {
			fmt.Printf("expected DOCDECL but got %s\n", PULL_EVENT_NAMES[event])
		}
	}
	c.Assert(event, Equals, DOCDECL)

	event, err = p.NextToken()
	c.Assert(err, IsNil)

	// Allow zero or more Misc but require the EmptyElement
	for event != START_TAG {
		if event == IGNORABLE_WHITESPACE || event == PROCESSING_INSTRUCTION ||
			event == COMMENT {

			event, err = p.NextToken()
		} else {
			fmt.Printf("expected START_TAG but got %s\n", PULL_EVENT_NAMES[event])
			break // XXX SHOULD FAIL
		}
	}
	c.Assert(err, IsNil)
	c.Assert(event, Equals, START_TAG)

	// allow any arbitrary number of Misc
	event, err = p.NextToken()
	// DEBUG
	fmt.Printf("DoParseBothDecl: NextToken => event %s, err %v\n",
		PULL_EVENT_NAMES[event], err)
	// END
	c.Assert(err == nil || err == io.EOF, Equals, true)
	fmt.Printf("err: %v\n", err)
	for event == IGNORABLE_WHITESPACE ||
		event == PROCESSING_INSTRUCTION || event == COMMENT {

		event, err = p.NextToken()
		// DEBUG
		fmt.Printf("DoParseBothDecl: NextToken => event %s, err %v\n",
			PULL_EVENT_NAMES[event], err)
		// END
		c.Assert(err == nil || err == io.EOF, Equals, true)
		fmt.Printf("err: %v\n", err)
	}
	c.Assert(event, Equals, END_DOCUMENT)
	return
}

func (s *XLSuite) TestParseEmptyElm(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_EMPTY_ELM")
	}
	s.doInitialParse(c, EMPTY_ELM)
}

func (s *XLSuite) TestParseXmlDeclPlusElm(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_XML_DECL_PLUS_ELM")
	}
	s.doParseXmlDecl(c, XML_DECL+EMPTY_ELM)
}

// Parse an XmlDecl followed by an (empty) element followed by Misc
func (s *XLSuite) TestParseXmlDeclPlusElmPlusMisc(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_XML_DECL_PLUS_ELM_PLUS_MISC")
	}
	rng := xr.MakeSimpleRNG()
	misc1 := s.createMiscItems(rng) // a small, possibly empty, slice
	miscN := s.createMiscItems(rng) // a small, possibly empty, slice
	s.doParseXmlDeclWithMisc(c, XML_DECL+s.textFromMISlice(misc1)+
		EMPTY_ELM+s.textFromMISlice(miscN), misc1)
}

func (s *XLSuite) TestParseBothDeclPlusElm(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_BOTH_DECL_PLUS_ELM")
	}
	s.doParseBothDecl(c, XML_DECL+DOCTYPE_DECL+EMPTY_ELM)
}

// Parse an XmlDecl followed a DocDecl followed by an (empty) element followed
// by Misc
// [1]  document ::= prolog element Misc*
// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
//
func (s *XLSuite) TestParseBothDeclPlusElmPlusMisc(c *C) {
	if VERBOSITY > 0 {
		fmt.Println("\nTEST_PARSE_BOTH_DECL_PLUS_ELM_PLUS_MISC")
	}
	rng := xr.MakeSimpleRNG()
	misc1 := s.createMiscItems(rng) // a small, possibly empty, slice
	misc2 := s.createMiscItems(rng) // a small, possibly empty, slice
	miscN := s.createMiscItems(rng) // a small, possibly empty, slice
	s.doParseBothDecl(c,
		XML_DECL+s.textFromMISlice(misc1)+
			DOCTYPE_DECL+s.textFromMISlice(misc2)+
			EMPTY_ELM+s.textFromMISlice(miscN))
}

// Simple test that constants and their string representations agree.
//
func (s *XLSuite) TestParserConst(c *C) {
	c.Assert(PARSER_STATE_NAMES[PRE_START_DOC], Equals, "PRE_START_DOC")
	c.Assert(PARSER_STATE_NAMES[START_ROOT_SEEN], Equals, "START_ROOT_SEEN")
	c.Assert(PARSER_STATE_NAMES[PAST_END_DOC], Equals, "PAST_END_DOC")
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strings"

	"zombiezen.com/go/capnproto2/internal/schema"
)

type node struct {
	schema.Node
	pkg   string
	imp   string
	nodes []*node // only for file nodes
	Name  string
}

func (n *node) codeOrderFields() []field {
	fields, _ := n.StructNode().Fields()
	numFields := fields.Len()
	mbrs := make([]field, numFields)
	for i := 0; i < numFields; i++ {
		f := fields.At(i)
		fann, _ := f.Annotations()
		fname, _ := f.Name()
		fname = parseAnnotations(fann).Rename(fname)
		mbrs[f.CodeOrder()] = field{Field: f, Name: fname}
	}
	return mbrs
}

// DiscriminantOffset returns the byte offset of the struct union discriminant.
func (n *node) DiscriminantOffset() (uint32, error) {
	if n == nil {
		return 0, errors.New("discriminant offset called on nil node")
	}
	if n.Which() != schema.Node_Which_structNode {
		return 0, fmt.Errorf("discriminant offset called on %v node", n.Which())
	}
	return n.StructNode().DiscriminantOffset() * 2, nil
}

func (n *node) shortDisplayName() string {
	dn, _ := n.DisplayName()
	return dn[n.DisplayNamePrefixLength():]
}

// String returns the node's display name.
func (n *node) String() string {
	return displayName(n)
}

func displayName(n interface {
	DisplayName() (string, error)
}) string {
	dn, _ := n.DisplayName()
	return dn
}

type field struct {
	schema.Field
	Name string
}

// HasDiscriminant reports whether the field is in a union.
func (f field) HasDiscriminant() bool {
	return f.DiscriminantValue() != schema.Field_noDiscriminant
}

type enumval struct {
	schema.Enumerant
	Name   string
	Val    int
	Tag    string
	parent *node
}

func makeEnumval(enum *node, i int, e schema.Enumerant) enumval {
	eann, _ := e.Annotations()
	ann := parseAnnotations(eann)
	name, _ := e.Name()
	name = ann.Rename(name)
	t := ann.Tag(name)
	return enumval{e, name, i, t, enum}
}

func (e *enumval) FullName() string {
	return e.parent.Name + "_" + e.Name
}

type interfaceMethod struct {
	schema.Method
	Interface    *node
	ID           int
	Name         string
	OriginalName string
	Params       *node
	Results      *node
}

func methodSet(methods []interfaceMethod, n *node, nodes nodeMap) ([]interfaceMethod, error) {
	ms, _ := n.Interface().Methods()
	for i := 0; i < ms.Len(); i++ {
		m := ms.At(i)
		mname, _ := m.Name()
		mann, _ := m.Annotations()
		pn, err := nodes.mustFind(m.ParamStructType())
		if err != nil {
			return methods, fmt.Errorf("could not find param type for %s.%s", n.shortDisplayName(), mname)
		}
		rn, err := nodes.mustFind(m.ResultStructType())
		if err != nil {
			return methods, fmt.Errorf("could not find result type for %s.%s", n.shortDisplayName(), mname)
		}
		methods = append(methods, interfaceMethod{
			Method:       m,
			Interface:    n,
			ID:           i,
			OriginalName: mname,
			Name:         parseAnnotations(mann).Rename(mname),
			Params:       pn,
			Results:      rn,
		})
	}
	// TODO(light): sort added methods by code order

	supers, _ := n.Interface().Superclasses()
	for i := 0; i < supers.Len(); i++ {
		s := supers.At(i)
		sn, err := nodes.mustFind(s.Id())
		if err != nil {
			return methods, fmt.Errorf("could not find superclass %#x of %s", s.Id(), n)
		}
		methods, err = methodSet(methods, sn, nodes)
		if err != nil {
			return methods, err
		}
	}
	return methods, nil
}

// Tag types
const (
	defaultTag = iota
	noTag
	customTag
)

type annotations struct {
	Doc       string
	Package   string
	Import    string
	TagType   int
	CustomTag string
	Name      string
}

func parseAnnotations(list schema.Annotation_List) *annotations {
	ann := new(annotations)
	for i, n := 0, list.Len(); i < n; i++ {
		a := list.At(i)
		val, _ := a.Value()
		text, _ := val.Text()
		switch a.Id() {
		case 0xc58ad6bd519f935e: // $doc
			ann.Doc = text
		case 0xbea97f1023792be0: // $package
			ann.Package = text
		case 0xe130b601260e44b5: // $import
			ann.Import = text
		case 0xa574b41924caefc7: // $tag
			ann.TagType = customTag
			ann.CustomTag = text
		case 0xc8768679ec52e012: // $notag
			ann.TagType = noTag
		case 0xc2b96012172f8df1: // $name
			ann.Name = text
		}
	}
	return ann
}

// Tag returns the string value that an enumerant value called name should have.
// An empty string indicates that this enumerant value has no tag.
func (ann *annotations) Tag(name string) string {
	switch ann.TagType {
	case noTag:
		return ""
	case customTag:
		return ann.CustomTag
	case defaultTag:
		fallthrough
	default:
		return name
	}
}

// Rename returns the overridden name from the annotations or the given name
// if no annotation was found.
func (ann *annotations) Rename(given string) string {
	if ann.Name == "" {
		return given
	}
	return ann.Name
}

type nodeMap map[uint64]*node

func buildNodeMap(req schema.CodeGeneratorRequest) (nodeMap, error) {
	rnodes, err := req.Nodes()
	if err != nil {
		return nil, err
	}
	nodes := make(nodeMap, rnodes.Len())
	var allfiles []*node
	for i := 0; i < rnodes.Len(); i++ {
		ni := rnodes.At(i)
		n := &node{Node: ni}
		nodes[n.Id()] = n
		if n.Which() == schema.Node_Which_file {
			allfiles = append(allfiles, n)
		}
	}
	for _, f := range allfiles {
		fann, err := f.Annotations()
		if err != nil {
			return nil, fmt.Errorf("reading annotations for %v: %v", f, err)
		}
		ann := parseAnnotations(fann)
		f.pkg = ann.Package
		f.imp = ann.Import
		nnodes, _ := f.NestedNodes()
		for i := 0; i < nnodes.Len(); i++ {
			nn := nnodes.At(i)
			if ni := nodes[nn.Id()]; ni != nil {
				nname, _ := nn.Name()
				if err := resolveName(nodes, ni, "", nname, f); err != nil {
					return nil, err
				}
			}
		}
	}
	return nodes, nil
}

// resolveName is called as part of building up a node map to populate the name field of n.
func resolveName(nodes nodeMap, n *node, base, name string, file *node) error {
	na, err := n.Annotations()
	if err != nil {
		return fmt.Errorf("reading annotations for %s: %v", n, err)
	}
	name = parseAnnotations(na).Rename(name)
	if base == "" {
		n.Name = strings.Title(name)
	} else {
		n.Name = base + "_" + name
	}
	n.pkg = file.pkg
	n.imp = file.imp
	file.nodes = append(file.nodes, n)

	nnodes, err := n.NestedNodes()
	if err != nil {
		return fmt.Errorf("listing nested nodes for %s: %v", n, err)
	}
	for i := 0; i < nnodes.Len(); i++ {
		nn := nnodes.At(i)
		ni := nodes[nn.Id()]
		if ni == nil {
			continue
		}
		nname, err := nn.Name()
		if err != nil {
			return fmt.Errorf("reading name of nested node %d in %s: %v", i+1, n, err)
		}
		if err := resolveName(nodes, ni, n.Name, nname, file); err != nil {
			return err
		}
	}

	switch n.Which() {
	case schema.Node_Which_structNode:
		fields, _ := n.StructNode().Fields()
		for i := 0; i < fields.Len(); i++ {
			f := fields.At(i)
			if f.Which() != schema.Field_Which_group {
				continue
			}
			fa, _ := f.Annotations()
			fname, _ := f.Name()
			grp := nodes[f.Group().TypeId()]
			if grp == nil {
				return fmt.Errorf("could not find type information for group %s in %s", fname, n)
			}
			fname = parseAnnotations(fa).Rename(fname)
			if err := resolveName(nodes, grp, n.Name, fname, file); err != nil {
				return err
			}
		}
	case schema.Node_Which_interface:
		m, _ := n.Interface().Methods()
		methodResolve := func(id uint64, mname string, base string, name string) error {
			x := nodes[id]
			if x == nil {
				return fmt.Errorf("could not find type %#x for %s.%s", id, n, mname)
			}
			if x.ScopeId() != 0 {
				return nil
			}
			return resolveName(nodes, x, base, name, file)
		}
		for i := 0; i < m.Len(); i++ {
			mm := m.At(i)
			mname, _ := mm.Name()
			mann, _ := mm.Annotations()
			base := n.Name + "_" + parseAnnotations(mann).Rename(mname)
			if err := methodResolve(mm.ParamStructType(), mname, base, "Params"); err != nil {
				return err
			}
			if err := methodResolve(mm.ResultStructType(), mname, base, "Results"); err != nil {
				return err
			}
		}
	}
	return nil
}

func (nm nodeMap) mustFind(id uint64) (*node, error) {
	n := nm[id]
	if n == nil {
		return nil, fmt.Errorf("could not find node %#x in schema", id)
	}
	return n, nil
}
<commit_msg>Move calls to val.Text() inside case branches. (#109)<commit_after>package main

import (
	"errors"
	"fmt"
	"strings"

	"zombiezen.com/go/capnproto2/internal/schema"
)

type node struct {
	schema.Node
	pkg   string
	imp   string
	nodes []*node // only for file nodes
	Name  string
}

func (n *node) codeOrderFields() []field {
	fields, _ := n.StructNode().Fields()
	numFields := fields.Len()
	mbrs := make([]field, numFields)
	for i := 0; i < numFields; i++ {
		f := fields.At(i)
		fann, _ := f.Annotations()
		fname, _ := f.Name()
		fname = parseAnnotations(fann).Rename(fname)
		mbrs[f.CodeOrder()] = field{Field: f, Name: fname}
	}
	return mbrs
}

// DiscriminantOffset returns the byte offset of the struct union discriminant.
func (n *node) DiscriminantOffset() (uint32, error) {
	if n == nil {
		return 0, errors.New("discriminant offset called on nil node")
	}
	if n.Which() != schema.Node_Which_structNode {
		return 0, fmt.Errorf("discriminant offset called on %v node", n.Which())
	}
	return n.StructNode().DiscriminantOffset() * 2, nil
}

func (n *node) shortDisplayName() string {
	dn, _ := n.DisplayName()
	return dn[n.DisplayNamePrefixLength():]
}

// String returns the node's display name.
func (n *node) String() string {
	return displayName(n)
}

func displayName(n interface {
	DisplayName() (string, error)
}) string {
	dn, _ := n.DisplayName()
	return dn
}

type field struct {
	schema.Field
	Name string
}

// HasDiscriminant reports whether the field is in a union.
func (f field) HasDiscriminant() bool {
	return f.DiscriminantValue() != schema.Field_noDiscriminant
}

type enumval struct {
	schema.Enumerant
	Name   string
	Val    int
	Tag    string
	parent *node
}

func makeEnumval(enum *node, i int, e schema.Enumerant) enumval {
	eann, _ := e.Annotations()
	ann := parseAnnotations(eann)
	name, _ := e.Name()
	name = ann.Rename(name)
	t := ann.Tag(name)
	return enumval{e, name, i, t, enum}
}

func (e *enumval) FullName() string {
	return e.parent.Name + "_" + e.Name
}

type interfaceMethod struct {
	schema.Method
	Interface    *node
	ID           int
	Name         string
	OriginalName string
	Params       *node
	Results      *node
}

func methodSet(methods []interfaceMethod, n *node, nodes nodeMap) ([]interfaceMethod, error) {
	ms, _ := n.Interface().Methods()
	for i := 0; i < ms.Len(); i++ {
		m := ms.At(i)
		mname, _ := m.Name()
		mann, _ := m.Annotations()
		pn, err := nodes.mustFind(m.ParamStructType())
		if err != nil {
			return methods, fmt.Errorf("could not find param type for %s.%s", n.shortDisplayName(), mname)
		}
		rn, err := nodes.mustFind(m.ResultStructType())
		if err != nil {
			return methods, fmt.Errorf("could not find result type for %s.%s", n.shortDisplayName(), mname)
		}
		methods = append(methods, interfaceMethod{
			Method:       m,
			Interface:    n,
			ID:           i,
			OriginalName: mname,
			Name:         parseAnnotations(mann).Rename(mname),
			Params:       pn,
			Results:      rn,
		})
	}
	// TODO(light): sort added methods by code order

	supers, _ := n.Interface().Superclasses()
	for i := 0; i < supers.Len(); i++ {
		s := supers.At(i)
		sn, err := nodes.mustFind(s.Id())
		if err != nil {
			return methods, fmt.Errorf("could not find superclass %#x of %s", s.Id(), n)
		}
		methods, err = methodSet(methods, sn, nodes)
		if err != nil {
			return methods, err
		}
	}
	return methods, nil
}

// Tag types
const (
	defaultTag = iota
	noTag
	customTag
)

type annotations struct {
	Doc       string
	Package   string
	Import    string
	TagType   int
	CustomTag string
	Name      string
}

func parseAnnotations(list schema.Annotation_List) *annotations {
	ann := new(annotations)
	for i, n := 0, list.Len(); i < n; i++ {
		a := list.At(i)
		val, _ := a.Value()
		switch a.Id() {
		case 0xc58ad6bd519f935e: // $doc
			ann.Doc, _ = val.Text()
		case 0xbea97f1023792be0: // $package
			ann.Package, _ = val.Text()
		case 0xe130b601260e44b5: // $import
			ann.Import, _ = val.Text()
		case 0xa574b41924caefc7: // $tag
			ann.TagType = customTag
			ann.CustomTag, _ = val.Text()
		case 0xc8768679ec52e012: // $notag
			ann.TagType = noTag
		case 0xc2b96012172f8df1: // $name
			ann.Name, _ = val.Text()
		}
	}
	return ann
}

// Tag returns the string value that an enumerant value called name should have.
// An empty string indicates that this enumerant value has no tag.
func (ann *annotations) Tag(name string) string {
	switch ann.TagType {
	case noTag:
		return ""
	case customTag:
		return ann.CustomTag
	case defaultTag:
		fallthrough
	default:
		return name
	}
}

// Rename returns the overridden name from the annotations or the given name
// if no annotation was found.
func (ann *annotations) Rename(given string) string {
	if ann.Name == "" {
		return given
	}
	return ann.Name
}

type nodeMap map[uint64]*node

func buildNodeMap(req schema.CodeGeneratorRequest) (nodeMap, error) {
	rnodes, err := req.Nodes()
	if err != nil {
		return nil, err
	}
	nodes := make(nodeMap, rnodes.Len())
	var allfiles []*node
	for i := 0; i < rnodes.Len(); i++ {
		ni := rnodes.At(i)
		n := &node{Node: ni}
		nodes[n.Id()] = n
		if n.Which() == schema.Node_Which_file {
			allfiles = append(allfiles, n)
		}
	}
	for _, f := range allfiles {
		fann, err := f.Annotations()
		if err != nil {
			return nil, fmt.Errorf("reading annotations for %v: %v", f, err)
		}
		ann := parseAnnotations(fann)
		f.pkg = ann.Package
		f.imp = ann.Import
		nnodes, _ := f.NestedNodes()
		for i := 0; i < nnodes.Len(); i++ {
			nn := nnodes.At(i)
			if ni := nodes[nn.Id()]; ni != nil {
				nname, _ := nn.Name()
				if err := resolveName(nodes, ni, "", nname, f); err != nil {
					return nil, err
				}
			}
		}
	}
	return nodes, nil
}

// resolveName is called as part of building up a node map to populate the name field of n.
func resolveName(nodes nodeMap, n *node, base, name string, file *node) error {
	na, err := n.Annotations()
	if err != nil {
		return fmt.Errorf("reading annotations for %s: %v", n, err)
	}
	name = parseAnnotations(na).Rename(name)
	if base == "" {
		n.Name = strings.Title(name)
	} else {
		n.Name = base + "_" + name
	}
	n.pkg = file.pkg
	n.imp = file.imp
	file.nodes = append(file.nodes, n)

	nnodes, err := n.NestedNodes()
	if err != nil {
		return fmt.Errorf("listing nested nodes for %s: %v", n, err)
	}
	for i := 0; i < nnodes.Len(); i++ {
		nn := nnodes.At(i)
		ni := nodes[nn.Id()]
		if ni == nil {
			continue
		}
		nname, err := nn.Name()
		if err != nil {
			return fmt.Errorf("reading name of nested node %d in %s: %v", i+1, n, err)
		}
		if err := resolveName(nodes, ni, n.Name, nname, file); err != nil {
			return err
		}
	}

	switch n.Which() {
	case schema.Node_Which_structNode:
		fields, _ := n.StructNode().Fields()
		for i := 0; i < fields.Len(); i++ {
			f := fields.At(i)
			if f.Which() != schema.Field_Which_group {
				continue
			}
			fa, _ := f.Annotations()
			fname, _ := f.Name()
			grp := nodes[f.Group().TypeId()]
			if grp == nil {
				return fmt.Errorf("could not find type information for group %s in %s", fname, n)
			}
			fname = parseAnnotations(fa).Rename(fname)
			if err := resolveName(nodes, grp, n.Name, fname, file); err != nil {
				return err
			}
		}
	case schema.Node_Which_interface:
		m, _ := n.Interface().Methods()
		methodResolve := func(id uint64, mname string, base string, name string) error {
			x := nodes[id]
			if x == nil {
				return fmt.Errorf("could not find type %#x for %s.%s", id, n, mname)
			}
			if x.ScopeId() != 0 {
				return nil
			}
			return resolveName(nodes, x, base, name, file)
		}
		for i := 0; i < m.Len(); i++ {
			mm := m.At(i)
			mname, _ := mm.Name()
			mann, _ := mm.Annotations()
			base := n.Name + "_" + parseAnnotations(mann).Rename(mname)
			if err := methodResolve(mm.ParamStructType(), mname, base, "Params"); err != nil {
				return err
			}
			if err := methodResolve(mm.ResultStructType(), mname, base, "Results"); err != nil {
				return err
			}
		}
	}
	return nil
}

func (nm nodeMap) mustFind(id uint64) (*node, error) {
	n := nm[id]
	if n == nil {
		return nil, fmt.Errorf("could not find node %#x in schema", id)
	}
	return n, nil
}
<|endoftext|>


<commit_before>package catalog

import (
	"fmt"
	"log"
	"sync"

	"github.com/dnaeon/gru/graph"
	"github.com/dnaeon/gru/resource"
	"github.com/dnaeon/gru/utils"
	"github.com/layeh/gopher-luar"
	"github.com/yuin/gopher-lua"
)

// Catalog type contains a collection of resources
type Catalog struct {
	// Unsorted contains the list of resources created by Lua
	Unsorted []resource.Resource `luar:"-"`

	// Collection contains the unsorted resources as a collection
	collection resource.Collection `luar:"-"`

	// Sorted contains the resources after a topological sort.
	sorted []*graph.Node `luar:"-"`

	// Reversed contains the resource dependency graph in reverse
	// order. It is used for finding the reverse dependencies of
	// resources.
	reversed *graph.Graph `luar:"-"`

	// Status contains status information about resources
	status *status `luar:"-"`

	// Configuration settings
	config *Config `luar:"-"`
}

// Config type represents a set of settings to use when
// creating and processing the catalog
type Config struct {
	// Name of the Lua module to load and execute
	Module string

	// Do not take any actions, just report what would be done
	DryRun bool

	// Writer used to log events
	Logger *log.Logger

	// Path to the site repo containing module and data files
	SiteRepo string

	// The Lua state
	L *lua.LState

	// Number of goroutines to use for concurrent processing
	Concurrency int
}

// status type contains status information about processed resources
type status struct {
	sync.RWMutex

	// Items contain the result of resource processing and any
	// errors that might have occurred during processing.
	// Keys of the map are the resource ids and their
	// values are the errors returned by resources.
	items map[string]error
}

// set sets the status for a resource
func (s *status) set(id string, err error) {
	s.Lock()
	defer s.Unlock()
	s.items[id] = err
}

// get retrieves the status of a resource
func (s *status) get(id string) (error, bool) {
	s.Lock()
	defer s.Unlock()
	err, ok := s.items[id]

	return err, ok
}

// isSynced returns a boolean indicating whether a
// resource is up to date
func (s *status) isSynced(id string) bool {
	s.Lock()
	defer s.Unlock()

	return s.items[id] == resource.ErrInSync
}

// hasFailed returns a boolean indicating whether a
// resource has failed during processing
func (s *status) hasFailed(id string) bool {
	s.Lock()
	defer s.Unlock()

	return s.items[id] != nil && s.items[id] != resource.ErrInSync
}

// New creates a new empty catalog with the provided configuration
func New(config *Config) *Catalog {
	c := &Catalog{
		config:     config,
		collection: make(resource.Collection),
		sorted:     make([]*graph.Node, 0),
		reversed:   graph.New(),
		status: &status{
			items: make(map[string]error),
		},
		Unsorted: make([]resource.Resource, 0),
	}

	// Inject the configuration for resources
	resource.DefaultConfig = &resource.Config{
		Logger:   config.Logger,
		SiteRepo: config.SiteRepo,
	}

	// Register the catalog type in Lua and also register
	// metamethods for the catalog, so that we can use
	// the catalog in a more Lua-friendly way
	mt := luar.MT(config.L, c)
	mt.RawSetString("__len", luar.New(config.L, (*Catalog).luaLen))
	config.L.SetGlobal("catalog", luar.New(config.L, c))

	return c
}

// Add adds a resource to the catalog.
// This method is called from Lua when adding new resources
func (c *Catalog) Add(resources ...resource.Resource) {
	for _, r := range resources {
		if r != nil {
			c.Unsorted = append(c.Unsorted, r)
		}
	}
}

// Load loads resources into the catalog
func (c *Catalog) Load() error {
	// Register the resource providers and catalog in Lua
	resource.LuaRegisterBuiltin(c.config.L)
	if err := c.config.L.DoFile(c.config.Module); err != nil {
		return err
	}

	// Perform a topological sort of the resources
	collection, err := resource.CreateCollection(c.Unsorted)
	if err != nil {
		return err
	}

	collectionGraph, err := collection.DependencyGraph()
	if err != nil {
		return err
	}

	reversed := collectionGraph.Reversed()

	sorted, err := collectionGraph.Sort()
	if err != nil {
		return err
	}

	// Set catalog fields
	c.collection = collection
	c.sorted = sorted
	c.reversed = reversed

	c.config.Logger.Printf("Loaded %d resources\n", len(c.sorted))

	return nil
}

// Run processes the resources from catalog
func (c *Catalog) Run() error {
	// process executes a single resource
	process := func(r resource.Resource) {
		id := r.ID()
		err := c.execute(r)
		c.status.set(id, err)
		if err != nil && err != resource.ErrInSync {
			c.config.Logger.Printf("%s %s\n", id, err)
		}
	}

	// Start goroutines for concurrent processing
	var wg sync.WaitGroup
	ch := make(chan resource.Resource, 1024)
	c.config.Logger.Printf("Starting %d goroutines for concurrent processing\n", c.config.Concurrency)
	for i := 0; i < c.config.Concurrency; i++ {
		wg.Add(1)
		worker := func() {
			defer wg.Done()
			for r := range ch {
				c.config.Logger.Printf("%s is concurrent", r.ID())
				process(r)
			}
		}
		go worker()
	}

	// Process the resources
	for _, node := range c.sorted {
		r := c.collection[node.Name]
		switch {
		// Resource is concurrent and is an isolated node
		case r.IsConcurrent() && len(r.Dependencies()) == 0 && len(c.reversed.Nodes[r.ID()].Edges) == 0:
			ch <- r
			continue
		// Resource is concurrent and has no reverse dependencies
		case r.IsConcurrent() && len(c.reversed.Nodes[r.ID()].Edges) == 0:
			ch <- r
			continue
		// Resource is not concurrent
		default:
			process(r)
		}
	}

	close(ch)
	wg.Wait()

	// Print summary report
	if !c.config.DryRun {
		var changed, failed, uptodate int
		for _, err := range c.status.items {
			switch err {
			case nil:
				changed++
			case resource.ErrInSync:
				uptodate++
			default:
				failed++
			}
		}
		c.config.Logger.Printf("Resource summary is %d up-to-date, %d changed, %d failed\n", uptodate, changed, failed)
	}

	return nil
}

// execute processes a single resource
func (c *Catalog) execute(r resource.Resource) error {
	// Check if the resource has failed dependencies
	for _, dep := range r.Dependencies() {
		if err, _ := c.status.get(dep); err != nil {
			return fmt.Errorf("failed dependency for %s", dep)
		}
	}

	if err := r.Validate(); err != nil {
		return err
	}

	state, err := r.Evaluate()
	if err != nil {
		return err
	}

	if c.config.DryRun {
		return nil
	}

	// Current and wanted states for the resource
	want := utils.NewString(state.Want)
	current := utils.NewString(state.Current)

	// The list of present and absent states for the resource
	present := utils.NewList(r.GetPresentStates()...)
	absent := utils.NewList(r.GetAbsentStates()...)

	id := r.ID()
	var action func() error
	switch {
	case want.IsInList(present) && current.IsInList(absent):
		action = r.Create
		c.config.Logger.Printf("%s is %s, should be %s\n", id, current, want)
	case want.IsInList(absent) && current.IsInList(present):
		action = r.Delete
		c.config.Logger.Printf("%s is %s, should be %s\n", id, current, want)
	case state.Outdated:
		action = r.Update
		c.config.Logger.Printf("%s is out of date\n", id)
	default:
		return resource.ErrInSync
	}

	return action()
}

// luaLen returns the number of unsorted resources in catalog.
// This method is called from Lua.
func (c *Catalog) luaLen() int {
	return len(c.Unsorted)
}
<commit_msg>catalog: implement method for checking if a resource state has changed<commit_after>package catalog

import (
	"fmt"
	"log"
	"sync"

	"github.com/dnaeon/gru/graph"
	"github.com/dnaeon/gru/resource"
	"github.com/dnaeon/gru/utils"
	"github.com/layeh/gopher-luar"
	"github.com/yuin/gopher-lua"
)

// Catalog type contains a collection of resources
type Catalog struct {
	// Unsorted contains the list of resources created by Lua
	Unsorted []resource.Resource `luar:"-"`

	// Collection contains the unsorted resources as a collection
	collection resource.Collection `luar:"-"`

	// Sorted contains the resources after a topological sort.
	sorted []*graph.Node `luar:"-"`

	// Reversed contains the resource dependency graph in reverse
	// order. It is used for finding the reverse dependencies of
	// resources.
	reversed *graph.Graph `luar:"-"`

	// Status contains status information about resources
	status *status `luar:"-"`

	// Configuration settings
	config *Config `luar:"-"`
}

// Config type represents a set of settings to use when
// creating and processing the catalog
type Config struct {
	// Name of the Lua module to load and execute
	Module string

	// Do not take any actions, just report what would be done
	DryRun bool

	// Writer used to log events
	Logger *log.Logger

	// Path to the site repo containing module and data files
	SiteRepo string

	// The Lua state
	L *lua.LState

	// Number of goroutines to use for concurrent processing
	Concurrency int
}

// status type contains status information about processed resources
type status struct {
	sync.RWMutex

	// Items contain the result of resource processing and any
	// errors that might have occurred during processing.
	// Keys of the map are the resource ids and their
	// values are the errors returned by resources.
	items map[string]error
}

// set sets the status for a resource
func (s *status) set(id string, err error) {
	s.Lock()
	defer s.Unlock()
	s.items[id] = err
}

// get retrieves the status of a resource
func (s *status) get(id string) (error, bool) {
	s.Lock()
	defer s.Unlock()
	err, ok := s.items[id]

	return err, ok
}

// isSynced returns a boolean indicating whether a
// resource is up to date
func (s *status) isSynced(id string) bool {
	s.Lock()
	defer s.Unlock()

	return s.items[id] == resource.ErrInSync
}

// hasChanged returns a boolean indicating whether a
// resource state has changed after processing
func (s *state) hasChanged(id string) bool {
	s.Lock()
	defer s.Unlock()

	return s.items[id] == nil
}

// hasFailed returns a boolean indicating whether a
// resource has failed during processing
func (s *status) hasFailed(id string) bool {
	s.Lock()
	defer s.Unlock()

	return s.items[id] != nil && s.items[id] != resource.ErrInSync
}

// New creates a new empty catalog with the provided configuration
func New(config *Config) *Catalog {
	c := &Catalog{
		config:     config,
		collection: make(resource.Collection),
		sorted:     make([]*graph.Node, 0),
		reversed:   graph.New(),
		status: &status{
			items: make(map[string]error),
		},
		Unsorted: make([]resource.Resource, 0),
	}

	// Inject the configuration for resources
	resource.DefaultConfig = &resource.Config{
		Logger:   config.Logger,
		SiteRepo: config.SiteRepo,
	}

	// Register the catalog type in Lua and also register
	// metamethods for the catalog, so that we can use
	// the catalog in a more Lua-friendly way
	mt := luar.MT(config.L, c)
	mt.RawSetString("__len", luar.New(config.L, (*Catalog).luaLen))
	config.L.SetGlobal("catalog", luar.New(config.L, c))

	return c
}

// Add adds a resource to the catalog.
// This method is called from Lua when adding new resources
func (c *Catalog) Add(resources ...resource.Resource) {
	for _, r := range resources {
		if r != nil {
			c.Unsorted = append(c.Unsorted, r)
		}
	}
}

// Load loads resources into the catalog
func (c *Catalog) Load() error {
	// Register the resource providers and catalog in Lua
	resource.LuaRegisterBuiltin(c.config.L)
	if err := c.config.L.DoFile(c.config.Module); err != nil {
		return err
	}

	// Perform a topological sort of the resources
	collection, err := resource.CreateCollection(c.Unsorted)
	if err != nil {
		return err
	}

	collectionGraph, err := collection.DependencyGraph()
	if err != nil {
		return err
	}

	reversed := collectionGraph.Reversed()

	sorted, err := collectionGraph.Sort()
	if err != nil {
		return err
	}

	// Set catalog fields
	c.collection = collection
	c.sorted = sorted
	c.reversed = reversed

	c.config.Logger.Printf("Loaded %d resources\n", len(c.sorted))

	return nil
}

// Run processes the resources from catalog
func (c *Catalog) Run() error {
	// process executes a single resource
	process := func(r resource.Resource) {
		id := r.ID()
		err := c.execute(r)
		c.status.set(id, err)
		if err != nil && err != resource.ErrInSync {
			c.config.Logger.Printf("%s %s\n", id, err)
		}
	}

	// Start goroutines for concurrent processing
	var wg sync.WaitGroup
	ch := make(chan resource.Resource, 1024)
	c.config.Logger.Printf("Starting %d goroutines for concurrent processing\n", c.config.Concurrency)
	for i := 0; i < c.config.Concurrency; i++ {
		wg.Add(1)
		worker := func() {
			defer wg.Done()
			for r := range ch {
				c.config.Logger.Printf("%s is concurrent", r.ID())
				process(r)
			}
		}
		go worker()
	}

	// Process the resources
	for _, node := range c.sorted {
		r := c.collection[node.Name]
		switch {
		// Resource is concurrent and is an isolated node
		case r.IsConcurrent() && len(r.Dependencies()) == 0 && len(c.reversed.Nodes[r.ID()].Edges) == 0:
			ch <- r
			continue
		// Resource is concurrent and has no reverse dependencies
		case r.IsConcurrent() && len(c.reversed.Nodes[r.ID()].Edges) == 0:
			ch <- r
			continue
		// Resource is not concurrent
		default:
			process(r)
		}
	}

	close(ch)
	wg.Wait()

	// Print summary report
	if !c.config.DryRun {
		var changed, failed, uptodate int
		for _, err := range c.status.items {
			switch err {
			case nil:
				changed++
			case resource.ErrInSync:
				uptodate++
			default:
				failed++
			}
		}
		c.config.Logger.Printf("Resource summary is %d up-to-date, %d changed, %d failed\n", uptodate, changed, failed)
	}

	return nil
}

// execute processes a single resource
func (c *Catalog) execute(r resource.Resource) error {
	// Check if the resource has failed dependencies
	for _, dep := range r.Dependencies() {
		if err, _ := c.status.get(dep); err != nil {
			return fmt.Errorf("failed dependency for %s", dep)
		}
	}

	if err := r.Validate(); err != nil {
		return err
	}

	state, err := r.Evaluate()
	if err != nil {
		return err
	}

	if c.config.DryRun {
		return nil
	}

	// Current and wanted states for the resource
	want := utils.NewString(state.Want)
	current := utils.NewString(state.Current)

	// The list of present and absent states for the resource
	present := utils.NewList(r.GetPresentStates()...)
	absent := utils.NewList(r.GetAbsentStates()...)

	id := r.ID()
	var action func() error
	switch {
	case want.IsInList(present) && current.IsInList(absent):
		action = r.Create
		c.config.Logger.Printf("%s is %s, should be %s\n", id, current, want)
	case want.IsInList(absent) && current.IsInList(present):
		action = r.Delete
		c.config.Logger.Printf("%s is %s, should be %s\n", id, current, want)
	case state.Outdated:
		action = r.Update
		c.config.Logger.Printf("%s is out of date\n", id)
	default:
		return resource.ErrInSync
	}

	return action()
}

// luaLen returns the number of unsorted resources in catalog.
// This method is called from Lua.
func (c *Catalog) luaLen() int {
	return len(c.Unsorted)
}
<|endoftext|>


<commit_before>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package buffer

import (
	"encoding/binary"
	"fmt"

	"github.com/garyburd/neovim-go/vim"
	"github.com/pkg/errors"
)

const (
	// Buffer options
	Filetype  = "filetype"
	Buftype   = "buftype"
	Bufhidden = "bufhidden"
	Buflisted = "buflisted"
	Swapfile  = "swapfile"

	// Window options
	List           = "list"
	Number         = "number"
	Relativenumber = "relativenumber"
	Winfixheight   = "winfixheight"

	FiletypeAsm     = "asm"
	FiletypeC       = "c"
	FiletypeCpp     = "cpp"
	FiletypeGo      = "go"
	BuftypeNofile   = "nofile"   // buffer which is not related to a file and will not be written.
	BuftypeNowrite  = "nowrite"  // buffer which will not be written.
	BuftypeAcwrite  = "acwrite"  // buffer which will always be written with BufWriteCmd autocommands.
	BuftypeQuickfix = "quickfix" // quickfix buffer, contains list of errors :cwindow or list of locations :lwindow
	BuftypeHelp     = "help"     // help buffer (you are not supposed to set this manually)
	BuftypeTerminal = "terminal" // terminal buffer, this is set automatically when a terminal is created. See nvim-terminal-emulator for more information.
	BufhiddenHide   = "hide"     // hide the buffer (don't unload it), also when 'hidden' is not set.
	BufhiddenUnload = "unload"   // unload the buffer, also when 'hidden' is set or using :hide.
	BufhiddenDelete = "delete"   // delete the buffer from the buffer list, also when 'hidden' is set or using :hide, like using :bdelete.
	BufhiddenWipe   = "wipe"     // wipe out the buffer from the buffer list, also when 'hidden' is set or using :hide, like using :bwipeout.
)

type Buffer struct {
	Buffer  vim.Buffer
	Window  vim.Window
	Tabpage vim.Tabpage

	Name  string
	Bufnr interface{}
	Mode  string
}

func NewBuffer(name string) *Buffer {
	b := &Buffer{
		Name: name,
	}

	return b
}

func (b *Buffer) Create(v *vim.Vim, bufOption, winOption map[string]interface{}) error {
	p := v.NewPipeline()
	p.Command(fmt.Sprintf("silent %s [delve] %s", b.Mode, b.Name))
	if err := p.Wait(); err != nil {
		return errors.Wrap(err, "Delve")
	}

	p.CurrentBuffer(&b.Buffer)
	p.CurrentWindow(&b.Window)
	if err := p.Wait(); err != nil {
		return errors.Wrap(err, "Delve")
	}

	p.Eval("bufnr('%')", b.Bufnr)
	for k, v := range bufOption {
		p.SetBufferOption(b.Buffer, k, v)
	}
	for k, v := range winOption {
		p.SetWindowOption(b.Window, k, v)
	}
	if err := p.Wait(); err != nil {
		return errors.Wrap(err, "Delve")
	}

	// TODO(zchee): Why can't set p.SetBufferOption?
	// p.Call("setbufvar", nil, b.bufnr.(int64), "&colorcolumn", "")

	return p.Wait()
}

// ByteOffset calculation of byte offset the current cursor position.
func ByteOffset(p *vim.Pipeline) (int, error) {
	var (
		b vim.Buffer
		w vim.Window
	)

	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return 0, err
	}

	var cursor [2]int
	p.WindowCursor(w, &cursor)

	var byteBuf [][]byte
	p.BufferLines(b, 0, -1, false, &byteBuf)

	if err := p.Wait(); err != nil {
		return 0, err
	}

	if cursor[0] == 1 {
		return (1 + (cursor[1] - 1)), nil
	}

	offset := 0
	line := 1
	for _, buf := range byteBuf {
		if line == cursor[0] {
			offset++
			break
		}
		offset += (binary.Size(buf) + 1)
		line++
	}

	return (offset + (cursor[1] - 1)), nil
}
<commit_msg>nvim/buffer: Fix error handle to juju/erros & Add SetMapping func<commit_after>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package buffer

import (
	"encoding/binary"
	"fmt"
	"nvim-go/nvim/profile"
	"time"

	"github.com/garyburd/neovim-go/vim"
	"github.com/juju/errors"
)

const (
	// Buffer options
	Bufhidden  = "bufhidden"  // string
	Buflisted  = "buflisted"  // bool
	Buftype    = "buftype"    // string
	Filetype   = "filetype"   // string
	Modifiable = "modifiable" // bool
	Modified   = "modified"   // bool
	Swapfile   = "swapfile"   // bool

	// Window options
	List           = "list"           // bool
	Number         = "number"         // bool
	Relativenumber = "relativenumber" // bool
	Winfixheight   = "winfixheight"   // bool
)

const (
	BufhiddenDelete = "delete"   // delete the buffer from the buffer list, also when 'hidden' is set or using :hide, like using :bdelete.
	BufhiddenHide   = "hide"     // hide the buffer (don't unload it), also when 'hidden' is not set.
	BufhiddenUnload = "unload"   // unload the buffer, also when 'hidden' is set or using :hide.
	BufhiddenWipe   = "wipe"     // wipe out the buffer from the buffer list, also when 'hidden' is set or using :hide, like using :bwipeout.
	BuftypeAcwrite  = "acwrite"  // buffer which will always be written with BufWriteCmd autocommands.
	BuftypeHelp     = "help"     // help buffer (you are not supposed to set this manually)
	BuftypeNofile   = "nofile"   // buffer which is not related to a file and will not be written.
	BuftypeNowrite  = "nowrite"  // buffer which will not be written.
	BuftypeQuickfix = "quickfix" // quickfix buffer, contains list of errors :cwindow or list of locations :lwindow
	BuftypeTerminal = "terminal" // terminal buffer, this is set automatically when a terminal is created. See nvim-terminal-emulator for more information.
	FiletypeAsm     = "asm"
	FiletypeC       = "c"
	FiletypeCpp     = "cpp"
	FiletypeGas     = "gas"
	FiletypeGo      = "go"
	FiletypeDelve   = "delve"
)

type Buffer struct {
	Buffer  vim.Buffer
	Window  vim.Window
	Tabpage vim.Tabpage

	Name  string
	Bufnr interface{}
	Mode  string
	Size  int
}

func NewBuffer(name string) *Buffer {
	b := &Buffer{
		Name: name,
	}

	return b
}

var (
	Map             = "map"
	MapNormal       = "nmap"
	MapVisualSelect = "vmap"
	MapSelect       = "smap"
	MapVisual       = "xmap"
	MapOperator     = "omap"
	MapInsert       = "imap"
	MapCLI          = "cmap"
	MapTerminal     = "tmap"

	Noremap             = "noremap"
	NoremapNormal       = "nnoremap"
	NoremapVisualSelect = "vnoremap"
	NoremapSelect       = "snoremap"
	NoremapVisual       = "xnoremap"
	NoremapOperator     = "onoremap"
	NoremapInsert       = "inoremap"
	NoremapCLI          = "cnoremap"
	NoremapTerminal     = "tnoremap"
)

func (b *Buffer) Create(v *vim.Vim, bufOption, winOption map[string]interface{}) error {
	defer profile.Start(time.Now(), "nvim/buffer.Create")

	p := v.NewPipeline()
	p.Command(fmt.Sprintf("silent %s [delve] %s", b.Mode, b.Name))
	if err := p.Wait(); err != nil {
		return errors.Annotate(err, "nvim/buffer.Create")
	}

	p.CurrentBuffer(&b.Buffer)
	p.CurrentWindow(&b.Window)
	p.CurrentTabpage(&b.Tabpage)
	p.Eval("bufnr('%')", &b.Bufnr)
	if err := p.Wait(); err != nil {
		return errors.Annotate(err, "nvim/buffer.Create")
	}

	if bufOption != nil {
		for k, op := range bufOption {
			p.SetBufferOption(b.Buffer, k, op)
		}
	}
	if winOption != nil {
		for k, op := range winOption {
			p.SetWindowOption(b.Window, k, op)
		}
	}
	p.Command(fmt.Sprintf("runtime! syntax/%s.vim", bufOption[Filetype]))
	if err := p.Wait(); err != nil {
		return errors.Annotate(err, "nvim/buffer.Create")
	}

	// TODO(zchee): Why can't set p.SetBufferOption?
	// p.Call("setbufvar", nil, b.Bufnr.(int64), "&colorcolumn", "")

	return p.Wait()
}

// SetBufferMapping sets buffer local mapping.
// 'mapping' arg: [key]{destination}
func (b *Buffer) SetMapping(v *vim.Vim, mode string, mapping map[string]string) error {
	p := v.NewPipeline()

	if mapping != nil {
		cwin, err := v.CurrentWindow()
		if err != nil {
			return errors.Annotate(err, "nvim/buffer.SetMapping")
		}

		p.SetCurrentWindow(b.Window)
		defer v.SetCurrentWindow(cwin)

		for k, v := range mapping {
			p.Command(fmt.Sprintf("silent %s <buffer><silent>%s %s", mode, k, v))
		}
	}

	return p.Wait()
}

// ByteOffset calculation of byte offset the current cursor position.
func ByteOffset(p *vim.Pipeline) (int, error) {
	var (
		b vim.Buffer
		w vim.Window
	)

	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return 0, err
	}

	var cursor [2]int
	p.WindowCursor(w, &cursor)

	var byteBuf [][]byte
	p.BufferLines(b, 0, -1, false, &byteBuf)

	if err := p.Wait(); err != nil {
		return 0, err
	}

	if cursor[0] == 1 {
		return (1 + (cursor[1] - 1)), nil
	}

	offset := 0
	line := 1
	for _, buf := range byteBuf {
		if line == cursor[0] {
			offset++
			break
		}
		offset += (binary.Size(buf) + 1)
		line++
	}

	return (offset + (cursor[1] - 1)), nil
}
<|endoftext|>


<commit_before>package dockerbuild

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	dockertypes "github.com/docker/engine-api/types"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	"github.com/spf13/cobra"

	"k8s.io/kubernetes/pkg/credentialprovider"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/util/interrupt"

	dockerbuilder "github.com/openshift/imagebuilder/dockerclient"
	cmdutil "github.com/openshift/origin/pkg/cmd/util"
	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
)

const (
	dockerbuildLong = `
Build a Dockerfile into a single layer

Builds the provided directory with a Dockerfile into a single layered image.
Requires that you have a working connection to a Docker engine. You may mount
secrets or config into the build with the --mount flag - these files will not
be included in the final image.

Experimental: This command is under active development and may change without notice.`

	dockerbuildExample = `  # Build the current directory into a single layer and tag
  %[1]s ex dockerbuild . myimage:latest

  # Mount a client secret into the build at a certain path
  %[1]s ex dockerbuild . myimage:latest --mount ~/mysecret.pem:/etc/pki/secret/mysecret.pem`
)

type DockerbuildOptions struct {
	Out io.Writer
	Err io.Writer

	Client *docker.Client

	MountSpecs []string

	Mounts         []dockerbuilder.Mount
	Directory      string
	Tag            string
	DockerfilePath string
	AllowPull      bool
	Keyring        credentialprovider.DockerKeyring
	Arguments      cmdutil.Environment
}

func NewCmdDockerbuild(fullName string, f *clientcmd.Factory, out, errOut io.Writer) *cobra.Command {
	options := &DockerbuildOptions{
		Out: out,
		Err: errOut,
	}
	cmd := &cobra.Command{
		Use:     "dockerbuild DIRECTORY TAG [--dockerfile=PATH]",
		Short:   "Perform a direct Docker build",
		Long:    dockerbuildLong,
		Example: fmt.Sprintf(dockerbuildExample, fullName),
		Run: func(cmd *cobra.Command, args []string) {
			kcmdutil.CheckErr(options.Complete(f, cmd, args))
			kcmdutil.CheckErr(options.Validate())
			if err := options.Run(); err != nil {
				// TODO: move met to kcmdutil
				if err == cmdutil.ErrExit {
					os.Exit(1)
				}
				kcmdutil.CheckErr(err)
			}
		},
	}

	cmd.Flags().StringSliceVar(&options.MountSpecs, "mount", options.MountSpecs, "An optional list of files and directories to mount during the build. Use SRC:DST syntax for each path.")
	cmd.Flags().StringVar(&options.DockerfilePath, "dockerfile", options.DockerfilePath, "An optional path to a Dockerfile to use.")
	cmd.Flags().BoolVar(&options.AllowPull, "allow-pull", true, "Pull the images that are not present.")
	cmd.MarkFlagFilename("dockerfile")

	return cmd
}

func (o *DockerbuildOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error {
	paths, envArgs, ok := cmdutil.SplitEnvironmentFromResources(args)
	if !ok {
		return kcmdutil.UsageError(cmd, "context directory must be specified before environment changes: %s", strings.Join(args, " "))
	}
	if len(paths) != 2 {
		return kcmdutil.UsageError(cmd, "the directory to build and tag must be specified")
	}
	o.Arguments, _, _ = cmdutil.ParseEnvironmentArguments(envArgs)
	o.Directory = paths[0]
	o.Tag = paths[1]
	if len(o.DockerfilePath) == 0 {
		o.DockerfilePath = filepath.Join(o.Directory, "Dockerfile")
	}

	var mounts []dockerbuilder.Mount
	for _, s := range o.MountSpecs {
		segments := strings.Split(s, ":")
		if len(segments) != 2 {
			return kcmdutil.UsageError(cmd, "--mount must be of the form SOURCE:DEST")
		}
		mounts = append(mounts, dockerbuilder.Mount{SourcePath: segments[0], DestinationPath: segments[1]})
	}
	o.Mounts = mounts

	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	o.Client = client

	o.Keyring = credentialprovider.NewDockerKeyring()

	return nil
}

func (o *DockerbuildOptions) Validate() error {
	return nil
}

func (o *DockerbuildOptions) Run() error {
	f, err := os.Open(o.DockerfilePath)
	if err != nil {
		return err
	}
	defer f.Close()
	e := dockerbuilder.NewClientExecutor(o.Client)
	e.Out, e.ErrOut = o.Out, o.Err
	e.AllowPull = o.AllowPull
	e.Directory = o.Directory
	e.TransientMounts = o.Mounts
	e.Tag = o.Tag
	e.AuthFn = func(image string) ([]dockertypes.AuthConfig, bool) {
		auth, ok := o.Keyring.Lookup(image)
		if !ok {
			return nil, false
		}
		var engineAuth []dockertypes.AuthConfig
		for _, c := range auth {
			engineAuth = append(engineAuth, c.AuthConfig)
		}
		return engineAuth, true
	}
	e.LogFn = func(format string, args ...interface{}) {
		if glog.V(2) {
			glog.Infof("Builder: "+format, args...)
		} else {
			fmt.Fprintf(e.ErrOut, "--> %s\n", fmt.Sprintf(format, args...))
		}
	}
	safe := interrupt.New(func(os.Signal) { os.Exit(1) }, func() {
		glog.V(5).Infof("invoking cleanup")
		if err := e.Cleanup(); err != nil {
			fmt.Fprintf(o.Err, "error: Unable to clean up build: %v\n", err)
		}
	})
	return safe.Run(func() error { return stripLeadingError(e.Build(f, o.Arguments)) })
}

func stripLeadingError(err error) error {
	if err == nil {
		return err
	}
	if strings.HasPrefix(err.Error(), "Error: ") {
		return fmt.Errorf(strings.TrimPrefix(err.Error(), "Error: "))
	}
	return err
}
<commit_msg>if err is nil return nil directly<commit_after>package dockerbuild

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	dockertypes "github.com/docker/engine-api/types"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	"github.com/spf13/cobra"

	"k8s.io/kubernetes/pkg/credentialprovider"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/util/interrupt"

	dockerbuilder "github.com/openshift/imagebuilder/dockerclient"
	cmdutil "github.com/openshift/origin/pkg/cmd/util"
	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
)

const (
	dockerbuildLong = `
Build a Dockerfile into a single layer

Builds the provided directory with a Dockerfile into a single layered image.
Requires that you have a working connection to a Docker engine. You may mount
secrets or config into the build with the --mount flag - these files will not
be included in the final image.

Experimental: This command is under active development and may change without notice.`

	dockerbuildExample = `  # Build the current directory into a single layer and tag
  %[1]s ex dockerbuild . myimage:latest

  # Mount a client secret into the build at a certain path
  %[1]s ex dockerbuild . myimage:latest --mount ~/mysecret.pem:/etc/pki/secret/mysecret.pem`
)

type DockerbuildOptions struct {
	Out io.Writer
	Err io.Writer

	Client *docker.Client

	MountSpecs []string

	Mounts         []dockerbuilder.Mount
	Directory      string
	Tag            string
	DockerfilePath string
	AllowPull      bool
	Keyring        credentialprovider.DockerKeyring
	Arguments      cmdutil.Environment
}

func NewCmdDockerbuild(fullName string, f *clientcmd.Factory, out, errOut io.Writer) *cobra.Command {
	options := &DockerbuildOptions{
		Out: out,
		Err: errOut,
	}
	cmd := &cobra.Command{
		Use:     "dockerbuild DIRECTORY TAG [--dockerfile=PATH]",
		Short:   "Perform a direct Docker build",
		Long:    dockerbuildLong,
		Example: fmt.Sprintf(dockerbuildExample, fullName),
		Run: func(cmd *cobra.Command, args []string) {
			kcmdutil.CheckErr(options.Complete(f, cmd, args))
			kcmdutil.CheckErr(options.Validate())
			if err := options.Run(); err != nil {
				// TODO: move met to kcmdutil
				if err == cmdutil.ErrExit {
					os.Exit(1)
				}
				kcmdutil.CheckErr(err)
			}
		},
	}

	cmd.Flags().StringSliceVar(&options.MountSpecs, "mount", options.MountSpecs, "An optional list of files and directories to mount during the build. Use SRC:DST syntax for each path.")
	cmd.Flags().StringVar(&options.DockerfilePath, "dockerfile", options.DockerfilePath, "An optional path to a Dockerfile to use.")
	cmd.Flags().BoolVar(&options.AllowPull, "allow-pull", true, "Pull the images that are not present.")
	cmd.MarkFlagFilename("dockerfile")

	return cmd
}

func (o *DockerbuildOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error {
	paths, envArgs, ok := cmdutil.SplitEnvironmentFromResources(args)
	if !ok {
		return kcmdutil.UsageError(cmd, "context directory must be specified before environment changes: %s", strings.Join(args, " "))
	}
	if len(paths) != 2 {
		return kcmdutil.UsageError(cmd, "the directory to build and tag must be specified")
	}
	o.Arguments, _, _ = cmdutil.ParseEnvironmentArguments(envArgs)
	o.Directory = paths[0]
	o.Tag = paths[1]
	if len(o.DockerfilePath) == 0 {
		o.DockerfilePath = filepath.Join(o.Directory, "Dockerfile")
	}

	var mounts []dockerbuilder.Mount
	for _, s := range o.MountSpecs {
		segments := strings.Split(s, ":")
		if len(segments) != 2 {
			return kcmdutil.UsageError(cmd, "--mount must be of the form SOURCE:DEST")
		}
		mounts = append(mounts, dockerbuilder.Mount{SourcePath: segments[0], DestinationPath: segments[1]})
	}
	o.Mounts = mounts

	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	o.Client = client

	o.Keyring = credentialprovider.NewDockerKeyring()

	return nil
}

func (o *DockerbuildOptions) Validate() error {
	return nil
}

func (o *DockerbuildOptions) Run() error {
	f, err := os.Open(o.DockerfilePath)
	if err != nil {
		return err
	}
	defer f.Close()
	e := dockerbuilder.NewClientExecutor(o.Client)
	e.Out, e.ErrOut = o.Out, o.Err
	e.AllowPull = o.AllowPull
	e.Directory = o.Directory
	e.TransientMounts = o.Mounts
	e.Tag = o.Tag
	e.AuthFn = func(image string) ([]dockertypes.AuthConfig, bool) {
		auth, ok := o.Keyring.Lookup(image)
		if !ok {
			return nil, false
		}
		var engineAuth []dockertypes.AuthConfig
		for _, c := range auth {
			engineAuth = append(engineAuth, c.AuthConfig)
		}
		return engineAuth, true
	}
	e.LogFn = func(format string, args ...interface{}) {
		if glog.V(2) {
			glog.Infof("Builder: "+format, args...)
		} else {
			fmt.Fprintf(e.ErrOut, "--> %s\n", fmt.Sprintf(format, args...))
		}
	}
	safe := interrupt.New(func(os.Signal) { os.Exit(1) }, func() {
		glog.V(5).Infof("invoking cleanup")
		if err := e.Cleanup(); err != nil {
			fmt.Fprintf(o.Err, "error: Unable to clean up build: %v\n", err)
		}
	})
	return safe.Run(func() error { return stripLeadingError(e.Build(f, o.Arguments)) })
}

func stripLeadingError(err error) error {
	if err == nil {
		return nil
	}
	if strings.HasPrefix(err.Error(), "Error: ") {
		return fmt.Errorf(strings.TrimPrefix(err.Error(), "Error: "))
	}
	return err
}
<|endoftext|>


<commit_before>// Package charset provides functions to decode and encode charsets.
package charset

import (
	"fmt"
	"io"
	"strings"

	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/encoding/traditionalchinese"
)

var charsets = map[string]encoding.Encoding{
	"big5":         traditionalchinese.Big5,
	"euc-jp":       japanese.EUCJP,
	"gbk":          simplifiedchinese.GBK,
	"gb2312":       simplifiedchinese.HZGB2312,
	"iso-2022-jp":  japanese.ISO2022JP,
	"iso-8859-1":   charmap.ISO8859_1,
	"iso-8859-2":   charmap.ISO8859_2,
	"iso-8859-3":   charmap.ISO8859_3,
	"iso-8859-4":   charmap.ISO8859_4,
	"iso-8859-10":  charmap.ISO8859_10,
	"iso-8859-13":  charmap.ISO8859_13,
	"iso-8859-14":  charmap.ISO8859_14,
	"iso-8859-15":  charmap.ISO8859_15,
	"iso-8859-16":  charmap.ISO8859_16,
	"koi8-r":       charmap.KOI8R,
	"shift_jis":    japanese.ShiftJIS,
	"windows-1250": charmap.Windows1250,
	"windows-1251": charmap.Windows1251,
	"windows-1252": charmap.Windows1252,
}

// Reader returns an io.Reader that converts the provided charset to UTF-8.
func Reader(charset string, input io.Reader) (io.Reader, error) {
	charset = strings.ToLower(charset)
	if charset == "utf-8" || charset == "us-ascii" {
		return input, nil
	}
	if enc, ok := charsets[charset]; ok {
		return enc.NewDecoder().Reader(input), nil
	}
	return nil, fmt.Errorf("unhandled charset %q", charset)
}
<commit_msg>change gb2312 back to use GBK<commit_after>// Package charset provides functions to decode and encode charsets.
package charset

import (
	"fmt"
	"io"
	"strings"

	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/encoding/traditionalchinese"
)

var charsets = map[string]encoding.Encoding{
	"big5":         traditionalchinese.Big5,
	"euc-jp":       japanese.EUCJP,
	"gbk":          simplifiedchinese.GBK,
	"gb2312":       simplifiedchinese.GBK, // as  GBK is a superset of HZGB2312,so just use GBK
	"iso-2022-jp":  japanese.ISO2022JP,
	"iso-8859-1":   charmap.ISO8859_1,
	"iso-8859-2":   charmap.ISO8859_2,
	"iso-8859-3":   charmap.ISO8859_3,
	"iso-8859-4":   charmap.ISO8859_4,
	"iso-8859-10":  charmap.ISO8859_10,
	"iso-8859-13":  charmap.ISO8859_13,
	"iso-8859-14":  charmap.ISO8859_14,
	"iso-8859-15":  charmap.ISO8859_15,
	"iso-8859-16":  charmap.ISO8859_16,
	"koi8-r":       charmap.KOI8R,
	"shift_jis":    japanese.ShiftJIS,
	"windows-1250": charmap.Windows1250,
	"windows-1251": charmap.Windows1251,
	"windows-1252": charmap.Windows1252,
}

// Reader returns an io.Reader that converts the provided charset to UTF-8.
func Reader(charset string, input io.Reader) (io.Reader, error) {
	charset = strings.ToLower(charset)
	if charset == "utf-8" || charset == "us-ascii" {
		return input, nil
	}
	if enc, ok := charsets[charset]; ok {
		return enc.NewDecoder().Reader(input), nil
	}
	return nil, fmt.Errorf("unhandled charset %q", charset)
}
<|endoftext|>