func (c *ContextBuilder) initEnv() *envctx.Env { env := envctx.FromContextOrNil(c.ctx) if env == nil { env = &envctx.Env{Aliases: map[string]string{}} c.ctx = envctx.NewContext(c.ctx, env) } return env }
func Context(path string) *ContextBuilder { env := &envctx.Env{ Path: path, Aliases: map[string]string{}, } ctx := context.Background() ctx = envctx.NewContext(ctx, env) return From(ctx) }
func scanForTypesAndExports(ctx context.Context, env *envctx.Env, cache *sysctx.SysPackageInfo, hash *PackageHasher) error { // While we're scanning for types, we should use a custom unpacking env, // because the env from the context is the one of the local package. files := scanner.ScanDirToFiles(ctx, env.Dir, env.Recursive) bytes := scanner.ScanFilesToBytes(ctx, files) localContext := envctx.NewContext(ctx, env) for b := range bytes { if b.Err != nil { return kerr.Wrap("JACKALTIGG", b.Err) } o := &system.ObjectStub{} if err := system.Unmarshal(localContext, b.Bytes, o); err != nil { return kerr.Wrap("HCYGNBDFFA", err) } if o.Type == nil { return kerr.New("NUKWIHYFMQ", "%s has no type", b.File) } if o.Id == nil && *o.Type != *system.NewReference("kego.io/system", "package") { // we tolerate missing ID only for system:package return kerr.New("DLLMKTDYFW", "%s has no id", b.File) } relativeFile, err := filepath.Rel(env.Dir, b.File) if err != nil { return kerr.Wrap("AWYRJSCYQS", err) } switch *o.Type { case *system.NewReference("kego.io/system", "type"): if err := ProcessTypeFileBytes(ctx, env, relativeFile, b.Bytes, cache, hash); err != nil { return kerr.Wrap("IVEFDDSKHE", err) } case *system.NewReference("kego.io/system", "package"): cache.PackageBytes = b.Bytes cache.PackageFilename = relativeFile default: cache.Globals.Set(o.Id.Name, relativeFile) if o.Export { cache.Exports.Set(o.Id.Name, o.Type.Name, o.Type.Package, b.Bytes) if hash != nil { hash.Exports[o.Id.Name+" "+o.Type.Name+" "+o.Type.Package] = cityhash.CityHash64(b.Bytes, uint32(len(b.Bytes))) } } } } return nil }
func Initialise(ctx context.Context, overrides OptionsInterface) (context.Context, context.CancelFunc, error) { if overrides == nil { overrides = Flags{} } options := overrides.getOptions() ctx, cancel := context.WithCancel(ctx) ctx = jsonctx.AutoContext(ctx) ctx = wgctx.NewContext(ctx) ctx = sysctx.NewContext(ctx) cmd := &cmdctx.Cmd{} vos := vosctx.FromContext(ctx) path := "" cmd.Edit = options.Edit cmd.Validate = options.Validate cmd.Update = options.Update cmd.Log = options.Log cmd.Debug = options.Debug cmd.Port = options.Port if options.Path == "" { dir, err := vos.Getwd() if err != nil { return nil, nil, kerr.Wrap("OKOLXAMBSJ", err) } p, err := packages.GetPackageFromDir(ctx, dir) if err != nil { return nil, nil, kerr.Wrap("ADNJKTLAWY", err) } path = p } else { path = options.Path } ctx = cmdctx.NewContext(ctx, cmd) pcache, err := parser.Parse(ctx, path) if err != nil { return nil, nil, kerr.Wrap("EBMBIBIKUF", err) } ctx = envctx.NewContext(ctx, pcache.Env) return ctx, cancel, nil }
func ProcessTypeFileBytes(ctx context.Context, env *envctx.Env, filename string, bytes []byte, cache *sysctx.SysPackageInfo, hash *PackageHasher) error { t := new(system.Type) if err := system.Unmarshal(envctx.NewContext(ctx, env), bytes, t); err != nil { return kerr.Wrap("NLRRVIDVWM", err) } if hash != nil { hash.Types[t.Id.Name] = cityhash.CityHash64(bytes, uint32(len(bytes))) } cache.Types.Set(t.Id.Name, filename, t) cache.Files.Set(t.Id.Name, filename, bytes) if t.Rule != nil { id := system.NewReference(t.Id.Package, fmt.Sprint("@", t.Id.Name)) if t.Rule.Id != nil && *t.Rule.Id != *id { return kerr.New("JKARKEDTIW", "Incorrect id for %v - it should be %v", t.Rule.Id.String(), id.String()) } t.Rule.Id = id // Check that the rule embeds system:rule found := false for _, em := range t.Rule.Embed { if *em == *system.NewReference("kego.io/system", "rule") { found = true } } if !found { return kerr.New("LMALEMKFDI", "%s does not embed system:rule", id.String()) } cache.Types.Set(id.Name, filename, t.Rule) } else { // If the rule is missing, automatically create a default. id := system.NewReference(t.Id.Package, fmt.Sprint("@", t.Id.Name)) rule := &system.Type{ Object: &system.Object{ Description: fmt.Sprintf("Automatically created basic rule for %s", t.Id.Name), Type: system.NewReference("kego.io/system", "type"), Id: id, }, Embed: []*system.Reference{system.NewReference("kego.io/system", "rule")}, Native: system.NewString("object"), Interface: false, } cache.Types.Set(id.Name, filename, rule) } return nil }
func Scan(ctx context.Context, path string) (*Package, error) { p := new(Package) // use a new system context for the duration of the scan ctx = sysctx.NewContext(ctx) env, err := parser.ScanForEnv(ctx, path) if err != nil { return nil, kerr.Wrap("SFPSTLPKMX", err) } p.Env = env files := scanner.ScanDirToFiles(ctx, env.Dir, env.Recursive) bytes := scanner.ScanFilesToBytes(ctx, files) localContext := envctx.NewContext(ctx, env) for b := range bytes { f := new(File) f.Package = p if b.Err != nil { return nil, kerr.Wrap("IPUHPBBWEA", b.Err) } o := &system.ObjectStub{} if err := system.Unmarshal(localContext, b.Bytes, o); err != nil { return nil, kerr.Wrap("DCAGIDLXRT", err) } if o.Type == nil { return nil, kerr.New("AJPCEQTWPS", "%s has no type", b.File) } if o.Id == nil && *o.Type != *system.NewReference("kego.io/system", "package") { // we tolerate missing ID only for system:package return nil, kerr.New("YDKYLXTGYC", "%s has no id", b.File) } f.AbsoluteFilepath = b.File f.Type = o.Type f.Id = o.Id if f.RelativeFilepath, err = filepath.Rel(env.Dir, b.File); err != nil { return nil, kerr.Wrap("QDAEGOWTWP", err) } f.Directory, f.Filename = filepath.Split(b.File) f.IsInRoot = DirEqual(f.Directory, env.Dir) f.Extension = filepath.Ext(b.File) f.Yaml = f.Extension == ".yaml" || f.Extension == ".yml" p.Files = append(p.Files, f) } return p, nil }
func scanForPackage(ctx context.Context, env *envctx.Env) (*system.Package, error) { localContext := envctx.NewContext(ctx, env) files := scanner.ScanDirToFiles(ctx, env.Dir, false) bytes := scanner.ScanFilesToBytes(ctx, files) for b := range bytes { if b.Err != nil { return nil, kerr.Wrap("GATNNQKNHY", b.Err, b.File) } o := &system.ObjectStub{} if err := system.Unmarshal(localContext, b.Bytes, o); err != nil { switch kerr.Source(err).(type) { case system.UnknownPackageError, system.UnknownTypeError: // don't return error default: return nil, kerr.Wrap("MTDCXBYBEJ", err, b.File) } } if o.Type == nil { return nil, kerr.New("MSNIGTIDIO", "%s has no type", b.File) } switch *o.Type { case *system.NewReference("kego.io/system", "package"): var i interface{} err := system.Unmarshal(localContext, b.Bytes, &i) if err != nil { switch kerr.Source(err).(type) { case system.UnknownPackageError, system.UnknownTypeError: // don't return error default: return nil, kerr.Wrap("XTEQCAYQJP", err) } } if pkg, ok := i.(*system.Package); ok { return pkg, nil } } } return nil, nil }
func (s *Server) Data(request *shared.DataRequest, response *shared.DataResponse) error { if !s.auth.Auth([]byte(request.Path), request.Hash) { return kerr.New("SYEKLIUMVY", "Auth failed") } env, err := parser.ScanForEnv(s.ctx, request.Package) if err != nil { return kerr.Wrap("PNAGGKHDYL", err) } full, err := pkghelp.Check(env.Dir, request.File, env.Recursive) if err != nil { return kerr.Wrap("JEYTFWKMYF", err) } bytes, err := scanner.ProcessFile(full) if err != nil { return kerr.Wrap("HQXMIMWXFY", err) } if bytes == nil { return kerr.New("HIUINHIAPY", "Error reading %s", request.File) } localContext := envctx.NewContext(s.ctx, env) o := &system.ObjectStub{} if err := system.Unmarshal(localContext, bytes, o); err != nil { return kerr.Wrap("SVINFEMKBG", err) } if o.Id.Name != request.Name { return kerr.New("TNJSLMPMLB", "Id %s in %s does not match request %s", o.Id.Name, request.File, request.Name) } response.Package = request.Package response.Name = request.Name response.Found = true response.Data = bytes return nil }
func NewContext(ctx context.Context, path string, aliases map[string]string) context.Context { ctx = envctx.NewContext(ctx, &envctx.Env{Path: path, Aliases: aliases}) ctx = jsonctx.AutoContext(ctx) return ctx }
func Start() error { loc := dom.GetWindow().Location() addr := fmt.Sprintf("ws://%s:%s/_rpc", loc.Hostname, loc.Port) ws, err := websocket.Dial(addr) if err != nil { return kerr.Wrap("HNQFLPFAJD", err) } app := &stores.App{ Conn: connection.New(rpc.NewClient(ws)), Fail: make(chan error), } // We parse the info attribute from the body tag info, err := getInfo(getRawInfo()) if err != nil { return kerr.Wrap("MGLVIQIDDY", err) } var ctx context.Context ctx = context.Background() ctx = envctx.NewContext(ctx, &envctx.Env{Path: info.Path, Aliases: info.Aliases}) ctx = sysctx.NewContext(ctx) ctx = jsonctx.AutoContext(ctx) ctx = stores.NewContext(ctx, app) ctx = clientctx.NewContext(ctx) app.Init(ctx) // Don't do this. Implement the Editable interface instead. We can't do // this for system types so we use this method instead. editors.Register(ctx) if _, err := registerTypes(ctx, info.Path, info.Imports); err != nil { return kerr.Wrap("MMJDDOBAUK", err) } p := views.NewPage(ctx) vecty.RenderBody(p) // TODO: work out why I can't seem to call this without using eval js.Global.Get("window").Call("eval", "Split(['#tree', '#main'], {sizes:[25, 75]});") app.Dispatch(&actions.InitialState{ Info: info, }) go func() { err, open := <-app.Fail if !open { // Channel has been closed, so app should gracefully exit. fmt.Println("Server disconnected") } else { // Error received, so app should display error. fmt.Println(err.Error()) } }() return nil }
func (s *Server) Save(request *shared.SaveRequest, response *shared.SaveResponse) error { if !s.auth.Auth([]byte(request.Path), request.Hash) { return kerr.New("GIONMMGOWA", "Auth failed") } pkg, err := pkghelp.Scan(s.ctx, request.Path) if err != nil { return kerr.Wrap("YKYVDSDGNV", err) } localContext := envctx.NewContext(s.ctx, pkg.Env) for _, info := range request.Files { // Check we only have yml, yaml or json extension. ext := filepath.Ext(info.File) if ext != ".json" && ext != ".yml" && ext != ".yaml" { return kerr.New("NDTPTCDOET", "Unsupported extension %s in %s", ext, info.File) } // Check the bytes are well formed json... o := &system.ObjectStub{} if err := system.Unmarshal(localContext, info.Bytes, o); err != nil { return kerr.Wrap("QISVPOXTCJ", err) } // Check type field exists if o.Type == nil { return kerr.New("PHINYFTGEC", "%s has no type", info.File) } // Check id field exists apart from system:package type. if o.Id == nil && *o.Type != *system.NewReference("kego.io/system", "package") { return kerr.New("NNOEQPRQXS", "%s has no id", info.File) } // Convert output to YAML if needed. output := info.Bytes if ext == ".yaml" || ext == ".yml" { var err error if output, err = yaml.JSONToYAML(output); err != nil { return kerr.Wrap("EAMEWSCAGB", err) } } var mode os.FileMode var full string file := pkg.File(info.File) if file != nil { // The file already exists, so we should use the existing filemode full = file.AbsoluteFilepath fs, err := os.Stat(full) if err != nil { return kerr.Wrap("VLIJSSVSXU", err) } mode = fs.Mode() } else { if full, err = pkghelp.Check(pkg.Env.Dir, info.File, pkg.Env.Recursive); err != nil { return kerr.Wrap("YSQEHPFIVF", err) } mode = 0644 if _, err := os.Stat(full); err == nil || !os.IsNotExist(err) { return kerr.New("XOEPAUNCXB", "Can't overwrite %s - existing file is not a valid ke data file", info.File) } } if err := ioutil.WriteFile(full, output, mode); err != nil { return kerr.Wrap("KPDYGCYOYQ", err) } response.Files = append(response.Files, shared.SaveResponseFile{ File: info.File, Hash: info.Hash, }) } return nil }