<commit_before>package gitfile

import (
	b64 "encoding/base64"
	"os/exec"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"github.com/hashicorp/terraform/helper/schema"
	"strings"
	"github.com/hashicorp/terraform/terraform"
)

func Provider() terraform.ResourceProvider {
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"workdir": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
		},
		ResourcesMap: map[string]*schema.Resource{
			"gitfile_file": fileResource(),
		},
		ConfigureFunc: gitfileConfigure,
	}
}

func gitfileConfigure(data *schema.ResourceData) (interface{}, error) {
	config := &gitfileConfig {
		workDir: data.Get("workdir").(string),
	}
	return config, nil
}

type gitfileConfig struct {
	workDir string
}

func fileResource() *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema {
			"repo": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"path": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"contents": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"branch": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "master",
			},
			"commit_message": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "Created by terraform gitfile_file",
			},
		},
		Create: FileCreate,
		Read: FileRead,
		Update: FileUpdate,
		Delete: FileDelete,
	}
}

func FileCreate(d *schema.ResourceData, meta interface{}) error {
	repo := d.Get("repo").(string)
	branch := d.Get("branch").(string)
	filepath := d.Get("path").(string)
	workdir := meta.(*gitfileConfig).workDir

	d.SetId(fmt.Sprintf("%s %s %s", repo, branch, filepath))

	checkout_dir := path.Join(workdir, mungeGitDir(d.Id()))
	if err := shallowSparseGitCheckout(checkout_dir, repo, branch, filepath); err != nil {
		return err
	}

	return FileUpdate(d, meta)
}
func FileRead(d *schema.ResourceData, meta interface{}) error {
	splits := strings.SplitN(d.Id(), " ", 3)
	repo := splits[0]
	branch := splits[1]
	filepath := splits[2]
	workdir := meta.(*gitfileConfig).workDir

	d.Set("repo", repo)
	d.Set("branch", branch)
	d.Set("path", filepath)

	checkout_dir := path.Join(workdir, mungeGitDir(d.Id()))
	if err := shallowSparseGitCheckout(checkout_dir, repo, branch, filepath); err != nil {
		return err
	}

	contents, err := ioutil.ReadFile(path.Join(checkout_dir, filepath))
	if err != nil {
		if os.IsNotExist(err) {
			d.Set("contents", "")
		} else {
			return err
		}
	} else {
		d.Set("contents", string(contents))
	}
	return nil
}
func FileUpdate(d *schema.ResourceData, meta interface{}) error {
	repo := d.Get("repo").(string)
	branch := d.Get("branch").(string)
	filepath := d.Get("path").(string)
	contents := d.Get("contents").(string)
	commit_message := d.Get("commit_message").(string)
	workdir := meta.(*gitfileConfig).workDir
	checkout_dir := path.Join(workdir, mungeGitDir(d.Id()))

	if err := ioutil.WriteFile(path.Join(checkout_dir, filepath), []byte(contents), 0666); err != nil {
		return err
	}

	// Only bother trying to commit things if the contents have changed.
	// I'm pretty sure this should be relatively accurate, since terraform will generally call FileRead before this.
	if d.HasChange("contents") {
		git_add := exec.Command("git", "add", "--intent-to-add", "--", filepath)
		git_add.Dir = checkout_dir
		if err := git_add.Run(); err != nil {
			return err
		}

		git_commit := exec.Command("git", "commit", "-m", commit_message, "--", filepath)
		git_commit.Dir = checkout_dir
		if err := git_commit.Run(); err != nil {
			return err
		}

		git_push := exec.Command("git", "push", repo, fmt.Sprintf("HEAD:%s", branch))
		git_push.Dir = checkout_dir
		if err := git_push.Run(); err != nil {
			return err
		}
	}
	return nil
}
func FileDelete(d *schema.ResourceData, meta interface{}) error {
	return nil
}


func mungeGitDir(id string) string {
	return b64.URLEncoding.EncodeToString([]byte(id))
}

func shallowSparseGitCheckout(checkout_dir, repo, branch, filepath string) error {
	if err := os.MkdirAll(checkout_dir, 0755); err != nil {
		return err
	}

	// git init appears to be idempotent.
	git_init := exec.Command("git", "init")
	git_init.Dir = checkout_dir
	if err := git_init.Run(); err != nil {
		return err
	}
<commit_msg>Delete semantics for gitfile_file<commit_after>package gitfile

import (
	b64 "encoding/base64"
	"os/exec"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"github.com/hashicorp/terraform/helper/schema"
	"strings"
	"syscall"
	"github.com/hashicorp/terraform/terraform"
)

func Provider() terraform.ResourceProvider {
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"workdir": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
		},
		ResourcesMap: map[string]*schema.Resource{
			"gitfile_file": fileResource(),
		},
		ConfigureFunc: gitfileConfigure,
	}
}

func gitfileConfigure(data *schema.ResourceData) (interface{}, error) {
	config := &gitfileConfig {
		workDir: data.Get("workdir").(string),
	}
	return config, nil
}

type gitfileConfig struct {
	workDir string
}

func fileResource() *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema {
			"repo": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"path": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"contents": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"branch": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "master",
			},
			"commit_message": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "Created by terraform gitfile_file",
			},
		},
		Create: FileCreate,
		Read: FileRead,
		Update: FileUpdate,
		Delete: FileDelete,
	}
}

func FileCreate(d *schema.ResourceData, meta interface{}) error {
	repo := d.Get("repo").(string)
	branch := d.Get("branch").(string)
	filepath := d.Get("path").(string)
	workdir := meta.(*gitfileConfig).workDir

	d.SetId(fmt.Sprintf("%s %s %s", repo, branch, filepath))

	checkout_dir := path.Join(workdir, mungeGitDir(d.Id()))
	if err := shallowSparseGitCheckout(checkout_dir, repo, branch, filepath); err != nil {
		return err
	}

	return FileUpdate(d, meta)
}
func FileRead(d *schema.ResourceData, meta interface{}) error {
	splits := strings.SplitN(d.Id(), " ", 3)
	repo := splits[0]
	branch := splits[1]
	filepath := splits[2]
	workdir := meta.(*gitfileConfig).workDir

	d.Set("repo", repo)
	d.Set("branch", branch)
	d.Set("path", filepath)

	checkout_dir := path.Join(workdir, mungeGitDir(d.Id()))
	if err := shallowSparseGitCheckout(checkout_dir, repo, branch, filepath); err != nil {
		return err
	}

	contents, err := ioutil.ReadFile(path.Join(checkout_dir, filepath))
	if err != nil {
		if os.IsNotExist(err) {
			d.Set("contents", "")
		} else {
			return err
		}
	} else {
		d.Set("contents", string(contents))
	}
	return nil
}
func FileUpdate(d *schema.ResourceData, meta interface{}) error {
	repo := d.Get("repo").(string)
	branch := d.Get("branch").(string)
	filepath := d.Get("path").(string)
	contents := d.Get("contents").(string)
	commit_message := d.Get("commit_message").(string)
	workdir := meta.(*gitfileConfig).workDir
	checkout_dir := path.Join(workdir, mungeGitDir(d.Id()))

	if err := ioutil.WriteFile(path.Join(checkout_dir, filepath), []byte(contents), 0666); err != nil {
		return err
	}

	// Only bother trying to commit things if the contents have changed.
	// I'm pretty sure this should be relatively accurate, since terraform will generally call FileRead before this.
	if d.HasChange("contents") {
		git_add := exec.Command("git", "add", "--intent-to-add", "--", filepath)
		git_add.Dir = checkout_dir
		if err := git_add.Run(); err != nil {
			return err
		}

		git_commit := exec.Command("git", "commit", "-m", commit_message, "--", filepath)
		git_commit.Dir = checkout_dir
		if err := git_commit.Run(); err != nil {
			return err
		}

		git_push := exec.Command("git", "push", repo, fmt.Sprintf("HEAD:%s", branch))
		git_push.Dir = checkout_dir
		if err := git_push.Run(); err != nil {
			return err
		}
	}
	return nil
}
func FileDelete(d *schema.ResourceData, meta interface{}) error {
	splits := strings.SplitN(d.Id(), " ", 3)
	repo := splits[0]
	branch := splits[1]
	filepath := splits[2]
	workdir := meta.(*gitfileConfig).workDir
	checkout_dir := path.Join(workdir, mungeGitDir(d.Id()))
	commit_message := d.Get("commit_message").(string)

	git_rm := exec.Command("git", "rm", "--ignore-unmatch", "--", filepath)
	git_rm.Dir = checkout_dir
	if err := git_rm.Run(); err != nil {
		return err
	}

	git_diff_index := exec.Command("git", "diff-index", "--exit-code", "--quiet", "HEAD", "--", filepath)
	git_diff_index.Dir = checkout_dir
	if err := git_diff_index.Run(); err != nil {
		exitErr, isExitErr := err.(*exec.ExitError)
		if isExitErr {
			if exitErr.Sys().(syscall.WaitStatus).ExitStatus() != 1 {
				return err
			} else {
				git_commit := exec.Command("git", "commit", "-m", commit_message, "--", filepath)
				git_commit.Dir = checkout_dir
				if err := git_commit.Run(); err != nil {
					return err
				}

				git_push := exec.Command("git", "push", repo, fmt.Sprintf("HEAD:%s", branch))
				git_push.Dir = checkout_dir
				if err := git_push.Run(); err != nil {
					return err
				}
			}
		} else {
			return err
		}
	}

	return nil
}


func mungeGitDir(id string) string {
	return b64.URLEncoding.EncodeToString([]byte(id))
}

func shallowSparseGitCheckout(checkout_dir, repo, branch, filepath string) error {
	if err := os.MkdirAll(checkout_dir, 0755); err != nil {
		return err
	}

	// git init appears to be idempotent.
	git_init := exec.Command("git", "init")
	git_init.Dir = checkout_dir
	if err := git_init.Run(); err != nil {
		return err
	}

{'fraction_non_alphanumeric': 0.1632902371984119, 'fraction_numerical': 0.004173877634123995, 'mean_word_length': 4.063917525773196, 'pattern_counts': {'":': 14, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '6468611', 'n_tokens_mistral': 3803, 'n_tokens_neox': 3445, 'n_words': 780}