<commit_before>/*
 Copyright 2015 Stack Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

package cli

import (
	"fmt"
	"log"
	"os"
	"strings"
)

// Structure representing a project
type Project struct {
	// Project name
	Name string

	// Base path of project
	BasePath string

	// Packages
	Packages []string

	// Capabilities
	Capabilities []string

	// Assembler compiler flags
	Aflags string

	// Compiler flags
	Cflags string

	// Linker flags
	Lflags string

	// The repository the project is located in
	Repo *Repo

	// The target associated with this project
	Target *Target
}

// Load and initialize a project specified by name
// r & t are the repository and target to associate the project with
func LoadProject(r *Repo, t *Target, name string) (*Project, error) {
	p := &Project{
		Name:   name,
		Repo:   r,
		Target: t,
	}

	log.Printf("[DEBUG] Loading project %s for repo %s, target %s",
		name, r.BasePath, t.Name)

	if err := p.Init(); err != nil {
		return nil, err
	} else {
		return p, nil
	}
}

// Get the packages associated with the project
func (p *Project) GetPackages() []string {
	return p.Packages
}

// Load project configuration
func (p *Project) loadConfig() error {
	log.Printf("[DEBUG] Reading Project configuration for %s in %s",
		p.Name, p.BasePath)

	v, err := ReadConfig(p.BasePath, p.Name)
	if err != nil {
		return err
	}

	t := p.Target

	p.Packages = GetStringSliceIdentities(v, t, "project.pkgs")

	idents := GetStringSliceIdentities(v, t, "project.identities")
	t.Identities = append(t.Identities, idents...)

	p.Capabilities = GetStringSliceIdentities(v, t, "project.caps")

	p.Cflags = GetStringIdentities(v, t, "project.cflags")
	p.Lflags = GetStringIdentities(v, t, "project.lflags")
	p.Aflags = GetStringIdentities(v, t, "project.aflags")

	return nil
}

// Clean the project build, and all packages that were built with the
// project, if cleanAll is true, then clean everything, not just the current
// architecture
func (p *Project) BuildClean(cleanAll bool) error {
	pm, err := NewPkgMgr(p.Repo, p.Target)
	if err != nil {
		return err
	}

	// first, clean packages
	log.Printf("[DEBUG] Cleaning all the packages associated with project %s",
		p.Name)
	for _, pkgName := range p.GetPackages() {
		err = pm.BuildClean(p.Target, pkgName, cleanAll)
		if err != nil {
			return err
		}
	}

	// clean the BSP
	if err := pm.BuildClean(p.Target, p.Target.Bsp, cleanAll); err != nil {
		return err
	}

	c, err := NewCompiler(p.Target.GetCompiler(), p.Target.Cdef, p.Target.Name, []string{})
	if err != nil {
		return err
	}

	tName := p.Target.Name
	if cleanAll {
		tName = ""
	}

	if err := c.RecursiveClean(p.BasePath, tName); err != nil {
		return err
	}

	return nil
}

// Build the packages that this project depends on
// pm is an initialized package manager, incls is an array of includes to append to
// (package includes get append as they are built), and libs is an array of archive
// files to append to (package libraries get appended as they are built)
func (p *Project) buildDeps(pm *PkgMgr, incls *[]string, libs *[]string) error {
	pkgList := p.GetPackages()
	if pkgList == nil {
		return nil
	}

	log.Printf("[INFO] Building package dependencies for project %s", p.Name)

	t := p.Target

	// Append project variables to target variables, so that all package builds
	// inherit from them
	pkgList = append(pkgList, t.Dependencies...)
	t.Capabilities = append(t.Capabilities, p.Capabilities...)
	t.Cflags += " " + p.Cflags
	t.Lflags += " " + p.Lflags
	t.Aflags += " " + p.Aflags

	// XXX: Should set these with target capabilities and dependencies!
	deps := map[string]*DependencyRequirement{}
	reqcaps := map[string]*DependencyRequirement{}
	caps := map[string]*DependencyRequirement{}

	for _, pkgName := range pkgList {
		if pkgName == "" {
			continue
		}

		pkg, err := pm.ResolvePkgName(pkgName)
		if err != nil {
			return err
		}

		if err := pm.CheckPkgDeps(pkg, deps, reqcaps, caps); err != nil {
			return err
		}
	}

	// After processing all the dependencies, verify that the package's capability
	// requirements are satisfies as well
	if err := pm.VerifyCaps(reqcaps, caps); err != nil {
		return err
	}

	// now go through and build everything
	for _, pkgName := range pkgList {
		if pkgName == "" {
			continue
		}<commit_msg>inherit capabilities from target and project.<commit_after>/*
 Copyright 2015 Stack Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

package cli

import (
	"fmt"
	"log"
	"os"
	"strings"
)

// Structure representing a project
type Project struct {
	// Project name
	Name string

	// Base path of project
	BasePath string

	// Packages
	Packages []string

	// Capabilities
	Capabilities []string

	// Assembler compiler flags
	Aflags string

	// Compiler flags
	Cflags string

	// Linker flags
	Lflags string

	// The repository the project is located in
	Repo *Repo

	// The target associated with this project
	Target *Target
}

// Load and initialize a project specified by name
// r & t are the repository and target to associate the project with
func LoadProject(r *Repo, t *Target, name string) (*Project, error) {
	p := &Project{
		Name:   name,
		Repo:   r,
		Target: t,
	}

	log.Printf("[DEBUG] Loading project %s for repo %s, target %s",
		name, r.BasePath, t.Name)

	if err := p.Init(); err != nil {
		return nil, err
	} else {
		return p, nil
	}
}

// Get the packages associated with the project
func (p *Project) GetPackages() []string {
	return p.Packages
}

// Load project configuration
func (p *Project) loadConfig() error {
	log.Printf("[DEBUG] Reading Project configuration for %s in %s",
		p.Name, p.BasePath)

	v, err := ReadConfig(p.BasePath, p.Name)
	if err != nil {
		return err
	}

	t := p.Target

	p.Packages = GetStringSliceIdentities(v, t, "project.pkgs")

	idents := GetStringSliceIdentities(v, t, "project.identities")
	t.Identities = append(t.Identities, idents...)

	p.Capabilities = GetStringSliceIdentities(v, t, "project.caps")

	p.Cflags = GetStringIdentities(v, t, "project.cflags")
	p.Lflags = GetStringIdentities(v, t, "project.lflags")
	p.Aflags = GetStringIdentities(v, t, "project.aflags")

	return nil
}

// Clean the project build, and all packages that were built with the
// project, if cleanAll is true, then clean everything, not just the current
// architecture
func (p *Project) BuildClean(cleanAll bool) error {
	pm, err := NewPkgMgr(p.Repo, p.Target)
	if err != nil {
		return err
	}

	// first, clean packages
	log.Printf("[DEBUG] Cleaning all the packages associated with project %s",
		p.Name)
	for _, pkgName := range p.GetPackages() {
		err = pm.BuildClean(p.Target, pkgName, cleanAll)
		if err != nil {
			return err
		}
	}

	// clean the BSP
	if err := pm.BuildClean(p.Target, p.Target.Bsp, cleanAll); err != nil {
		return err
	}

	c, err := NewCompiler(p.Target.GetCompiler(), p.Target.Cdef, p.Target.Name, []string{})
	if err != nil {
		return err
	}

	tName := p.Target.Name
	if cleanAll {
		tName = ""
	}

	if err := c.RecursiveClean(p.BasePath, tName); err != nil {
		return err
	}

	return nil
}

// Build the packages that this project depends on
// pm is an initialized package manager, incls is an array of includes to append to
// (package includes get append as they are built), and libs is an array of archive
// files to append to (package libraries get appended as they are built)
func (p *Project) buildDeps(pm *PkgMgr, incls *[]string, libs *[]string) error {
	pkgList := p.GetPackages()
	if pkgList == nil {
		return nil
	}

	log.Printf("[INFO] Building package dependencies for project %s", p.Name)

	t := p.Target

	// Append project variables to target variables, so that all package builds
	// inherit from them
	pkgList = append(pkgList, t.Dependencies...)
	t.Capabilities = append(t.Capabilities, p.Capabilities...)
	t.Cflags += " " + p.Cflags
	t.Lflags += " " + p.Lflags
	t.Aflags += " " + p.Aflags

	deps := map[string]*DependencyRequirement{}
	reqcaps := map[string]*DependencyRequirement{}
	caps := map[string]*DependencyRequirement{}

	// inherit project capabilities, mark these capabilities as supported.
	for _, cName := range t.Capabilities {
		dr, err := NewDependencyRequirementParseString(cName)
		if err != nil {
			return err
		}

		caps[dr.String()] = dr
	}

	for _, pkgName := range pkgList {
		if pkgName == "" {
			continue
		}

		pkg, err := pm.ResolvePkgName(pkgName)
		if err != nil {
			return err
		}

		if err := pm.CheckPkgDeps(pkg, deps, reqcaps, caps); err != nil {
			return err
		}
	}

	// After processing all the dependencies, verify that the package's capability
	// requirements are satisfies as well
	if err := pm.VerifyCaps(reqcaps, caps); err != nil {
		return err
	}

	// now go through and build everything
	for _, pkgName := range pkgList {
		if pkgName == "" {
			continue
		}
{'fraction_non_alphanumeric': 0.11394088166104122, 'fraction_numerical': 0.0016364938120077735, 'mean_word_length': 3.5289485873089395, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3656525', 'n_tokens_mistral': 3245, 'n_tokens_neox': 3090, 'n_words': 1136}