package main

import (
    "fmt"
    "os"
    "os/exec"
	"log"
	"bytes"
	"path/filepath"
	"strings"
	"strconv"
	"io"
	"io/ioutil"
	"hash"
	"crypto/sha256"
	"crypto/sha512"
    "bufio"
    "unicode"
    "debug/elf"
    "text/template"
    "gopkg.in/ini.v1"

)

var pkg_env []string

var srcdir string
var pkgdir string
var archive string

var CurDir string

var log_file *os.File
var cfg *ini.File
var build_sections map[string]string
//var source_def map[string]string

type Talimat struct {
  // paket
  name string
  version string
  release string
  desc string
  packager string
  group string
  url string
  srcdir string
  tdir string
  // build
  build string
  install string
  sources []Source
  hashes []Hash
} 

type Source struct {
  // kaynak
  path string
  store string
  stype string
  order string
  extract bool
} 

type Hash struct {
  // hash
  htype string
  value string
  order string
} 

 	
func check(e error) {
    if e != nil {
        panic(e)
    }
}

func downloadFile(url string, filepath string) bool {
	cmd_check := "curl --head %s"
	//HTTP/2 200
	// todo: dosya var mı kontrol edilcek net/http ile olabilir
	out := process_cmd(fmt.Sprintf(cmd_check,url),true,false,true)
	//fmt.Println(out)
	if !strings.Contains(out,"404 Not Found") {
		cmd_str := "curl --progress-bar -L %s --output %s"
		process_cmd(fmt.Sprintf(cmd_str,url,filepath),true,true,false)
		return true
	} else {
		log.Fatal("Dosya bulunamadı:", url)
		return false
	}
}

func gitClone(url string, filepath string) {
	cmd_str := "git clone %s %s"
	process_cmd(fmt.Sprintf(cmd_str,url,filepath),true,true,false)
}

func gitPull(filepath string) {
	cmd_str := "cd %s ;git pull"
	process_cmd(fmt.Sprintf(cmd_str,filepath),true,true,false)
}

func copy_file(src string, dest string) bool {
	input, err := ioutil.ReadFile(src)
	if err != nil {
	  fmt.Println(err)
	  return false
	}

	err = ioutil.WriteFile(dest, input, 0644)
	if err != nil {
	  fmt.Println("Error creating", dest)
	  fmt.Println(err)
	  return false
	}
	return true	
}

func calculate_hash(htype string, file string) string {

	f, err := os.Open(file)
	if err != nil {
	  log.Fatal(err)
	}
	//defer f.Close()
	
	var h hash.Hash
	
	if htype == "sha256" { 
		h = sha256.New() 
	} else if htype == "sha512" { 
		h = sha512.New() 
	} else {
		log.Fatal("tanımsız hash tipi", htype)
	}
	if _, err := io.Copy(h, f); err != nil {
	  log.Fatal(err)
	}
	f.Close()
	return fmt.Sprintf("%x", h.Sum(nil))
}

// check for path traversal and correct forward slashes
func validRelPath(p string) bool {
	if p == "" || strings.Contains(p, `\`) || strings.HasPrefix(p, "/") || strings.Contains(p, "../") {
		return false
	}
	return true
}

func isDir(path string) bool {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	return fileInfo.IsDir()
}

func add2env(key string, value string){
	pkg_env = append(pkg_env, fmt.Sprintf("%s=%s", key, value))
}

func prepare_pkg_env(pkg *Talimat){
	add2env("isim",pkg.name)
	add2env("surum",pkg.version)
	add2env("devir",pkg.release)
	add2env("url",pkg.url)
	add2env("SRC_DIR",pkg.srcdir)
	add2env("TDIR",pkg.tdir)
}

func prepare_env(){
  for _, key := range cfg.Section("export").Keys() {
      add2env(key.Name(), cfg.Section("export").Key(key.Name()).String())
  }
  for _, key := range cfg.Section("source_site").Keys() {
      add2env(key.Name(), cfg.Section("source_site").Key(key.Name()).String())
  }
}

func create_dirs(){
	srcdir = cfg.Section("export").Key("SRC").String() + "/"
    pkgdir = cfg.Section("export").Key("PKG").String() + "/"
    archive = cfg.Section("export").Key("SOURCES_DIR").String() + "/"
    // silinmeli mi?
    os.RemoveAll(srcdir)
    os.RemoveAll(pkgdir)
    os.MkdirAll(srcdir, os.ModePerm)
    os.MkdirAll(pkgdir, os.ModePerm)
}

func (pkg Talimat) Print() {
  metainfo := fmt.Sprintf(`[paket]
isim=%s
surum=%s
devir=%s
tanim=%s
url=%s
paketci=%s
grup=%s
arsiv=%s
	`, pkg.name, pkg.version, pkg.release, pkg.desc, pkg.url, pkg.packager, pkg.group, pkg.srcdir)
  fmt.Println(metainfo)
  fmt.Println("[kaynak]")
  for _, s := range pkg.sources {
	fmt.Printf("%s =%s|%s->%s\n", s.order, s.stype,  s.path, s.store)
  }
  fmt.Println("[hash]")
  for _, h := range pkg.hashes {
	fmt.Printf("%s =%s|%s\n", h.order, h.htype,  h.value)
  }
  fmt.Println("[derle]")
  fmt.Println(pkg.build)
  fmt.Println("[pakur]")
  fmt.Println(pkg.install)
}

func evalsh(expr string) string {
	//fmt.Println("evalsh:",expr)
	cmd := exec.Command("bash", "-c","echo "+ expr)
	cmd.Env = os.Environ()
	for _, envar := range pkg_env {
		cmd.Env = append(cmd.Env, envar)
	}
	var outb, errb bytes.Buffer
	cmd.Stdout = &outb
	cmd.Stderr = &errb
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
	//fmt.Println("evalsh:",expr,strings.TrimSuffix(outb.String(), "\n"))
	return strings.TrimSuffix(outb.String(), "\n")
} 

func process_cmd(cmd_str string, debug bool, logto bool, output bool) string{
	// build,install -> true,true,false
	// cmd output -> true,false,true
	if debug {
		cmd_str = "set -x;" + cmd_str
	}
	cmd := exec.Command("bash","-c",cmd_str)
	//cmd := exec.Command("bash", "-c",cmd_str)
	cmd.Env = os.Environ()
	for _, envar := range pkg_env {
		//fmt.Println("envar:",envar)
		cmd.Env = append(cmd.Env, evalsh(envar))		
	}
	//for _,x := range cmd.Env {fmt.Println("...",x)}
	stdout, err := cmd.StdoutPipe()
	check(err)
	// hata konsolunu out a eşitleme
	cmd.Stderr = cmd.Stdout
	//if err != nil { fmt.Println("process_cmd_stdoutpipe:",err) }
	err = cmd.Start()
	check(err)
	//if err != nil { fmt.Println("process_cmd_start:",err) }
	if logto {
		// print the output of the subprocess stdout and logfile
		wlog := bufio.NewWriter(log_file)
		log_file.Sync()
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			m := scanner.Text()
			fmt.Println(m)
			// log dosyasına da yazılacak.
			//n4, err := w.WriteString("buffered\n")
			wlog.WriteString(m+"\n")
		}
		if err := cmd.Wait(); err != nil {
			log.Fatal("Çalıştırma betik hatası:", err)
			
		}
		wlog.Flush()
		return "OK"
	} 
	if output {
		outstr := ""
		reader := bufio.NewReader(stdout)
		line, err := reader.ReadString('\n')
		for err == nil {
			outstr += line
			line, err = reader.ReadString('\n')
		}
		cmd.Wait()
		return outstr
	}
	return ""
}

func parse_headers(talimat *ini.File, pkg *Talimat) {
	talimat_dir := filepath.Base(pkg.tdir)
	pkg.name = strings.Split(talimat_dir, "#")[0]
    pkg.version = strings.Split(strings.Split(talimat_dir, "#")[1], "-")[0]
    pkg.release = strings.Split(strings.Split(talimat_dir, "#")[1], "-")[1]
    pkg.desc = talimat.Section("paket").Key("tanim").String()
    pkg.packager = talimat.Section("paket").Key("paketci").String()
    pkg.group = talimat.Section("paket").Key("grup").String()
    pkg.url = talimat.Section("paket").Key("url").String()
    pkg.srcdir = talimat.Section("paket").Key("arsiv").String()
    if pkg.srcdir == "" {
		pkg.srcdir = srcdir+pkg.name+"-"+pkg.version
	} else {
		pkg.srcdir = srcdir+pkg.srcdir
	}
	pkg.build   = fmt.Sprintf("cd %s\n",pkg.srcdir)
	pkg.install = pkg.build
}

func parse_sources(talimat *ini.File, pkg *Talimat) {
    s_name := ""
	s_url := ""
	s_type := "url"
	count := 0
	var str string
	var extract_state bool
    for _,k := range talimat.Section("kaynak").Keys() { 
		for _, v := range k.ValueWithShadows() {
			var value bytes.Buffer
			//fmt.Println("--",v)
			extract_state = true
			str = ""
			t_str := cfg.Section("source").Key(k.Name()).String()
			t := template.Must(template.New("tpl").Parse(t_str))
			t.Execute(&value, v)
			str = value.String()
			if str != "" {
				v = str
			}
			
			if strings.Contains(v,"!"){
				v = strings.Replace(v, "!","",1)
				extract_state = false
			}
			
			if strings.Contains(v,"::"){
				s_url = strings.Split(v, "::")[0]
				s_name = strings.Split(v, "::")[1]
				s_name = archive + evalsh(s_name)
			}
			
			
			if k.Name() == "git" {
				s_type = "git"
			}
			if k.Name() == "dosya" {
				s_url = pkg.tdir +"/"+ evalsh(v)
				s_name = srcdir + evalsh(v)
				s_type = "file"
			} 
			if s_name == "" {
				s_url = evalsh(v)
				s_name = s_url[strings.LastIndex(s_url, "/")+1:]
				s_name = archive + s_name
			}
			count += 1
		    pkg.sources = append(pkg.sources, Source{order: string(count), stype: s_type, path: s_url, store: s_name, extract: extract_state})
		    s_name, s_url = "",""
		    s_type = "url"
		}
	}
	fmt.Println("----",pkg.sources)
}

func parse_hashes(talimat *ini.File, pkg *Talimat) {
    for _, hashkey := range []string{"sha256","sha512"} {
		for _,k := range talimat.Section(hashkey).Keys() {	
			pkg.hashes = append(pkg.hashes, 
			Hash{htype: hashkey, order: k.Name(), 
			value:talimat.Section(hashkey).Key(k.Name()).String()})
		}
	}
}

func fetch_sources(talimat *ini.File, pkg *Talimat) {
	for _, source := range pkg.sources {
		//fmt.Println(source.stype +":"+ source.path +"->"+ source.store)
		if _, err := os.Stat(source.store); err == nil {
			log.Println("dosya zaten var:",source.store)
			// git ise pull
			if source.stype == "git" {
				gitPull(source.store)
				// srcdir kopyalama kontrol
				if _, err := os.Stat(pkg.srcdir); err != nil {
					process_cmd(fmt.Sprintf("cp -r %s %s",source.store, pkg.srcdir),true,true,false)
				}
				
			}
			continue; 
		}
		if source.stype == "file" {
		  if copy_file(source.path,source.store) {
		    log.Println("dosya kopyalama:",source.store)
		  }
		} else if source.stype == "url" {
			if !downloadFile(source.path,source.store) {
				log.Fatal("dosya indirme hatası:",source.path)
			}
			//log.Println("dosya kopyalama:",source.store)
		} else if source.stype == "git" {
			gitClone(source.path,source.store)
			log.Println("----------------------")
			process_cmd(fmt.Sprintf("cp -r %s %s",source.store, pkg.srcdir),true,true,false)
			//log.Fatal("git dizin kopyalama hatası:",source.path)
		} else {
			log.Fatal("dosya belirsiz indirme tipi:",source.stype)
		}
	}
}

func check_sources(talimat *ini.File, pkg *Talimat) bool {
    log.Println("Dosyaların tutarlılık kontrolü yapılacak.")
    nr := 0
    file := ""
    for _,hash := range pkg.hashes { 	
		nr, _ = strconv.Atoi(hash.order)
		file = pkg.sources[nr-1].store
		if !isDir(file) {
			if hash.value == calculate_hash(hash.htype, file) {
				fmt.Println(file,"+")
			} else {
				log.Fatal(file,"-")
				return false
			}
		} else {
			log.Println("Hash kontrol dizin için pas geçildi",file)
		}
	}
	return true
}

func extract_sources(talimat *ini.File, pkg *Talimat) bool {
    log.Println("Dosyaların dışarı çıkarması yapılacak.")
	for _,source := range pkg.sources { 	
		if source.stype == "file" || source.stype == "git" || !source.extract {continue;}
		cmd := fmt.Sprintf("tar xf %s -C %s",source.store,srcdir)
		process_cmd(cmd,true,true,false)
	}
	return true
}

func parse_build(talimat *ini.File, pkg *Talimat, section string) {
    body := talimat.Section(section).Body()
    for _,line := range strings.Split(body,"\n") { 
		k := strings.TrimRightFunc(strings.Split(line,"=")[0],unicode.IsSpace)
		v := strings.Replace(line,k,"",1)
		v  = strings.Replace(v,"=","",1)
		v  = strings.TrimLeftFunc(v, unicode.IsSpace)
		var value bytes.Buffer
		t_str := cfg.Section(build_sections[section]).Key(k).String()
		t := template.Must(template.New("tpl").Parse(t_str))
		t.Execute(&value, v)
		str := value.String()
		for _, sec := range []string{"build_type","install_type"} {
			if sec == str {
				str = cfg.Section(str).Key(v).String()
			}
		}
		/*
		// dosya içerik okuma ile
		if strings.Contains(strings.Split(line, "=")[0],"dosya") {
		  build_file := strings.TrimLeftFunc(strings.TrimRightFunc(strings.Split(line, "=")[1],unicode.IsSpace),unicode.IsSpace)
		  build_content, _ := ioutil.ReadFile(pkg.tdir+"/"+build_file)
		  pkg.build += string(build_content) + "\n"	
		}
		*/
		if build_sections[section] == "build" {
			pkg.build += str + "\n"			
		}
		if build_sections[section] == "install" {
			pkg.install += str + "\n"
		}
	}
}

func build_package(pkg *Talimat) {
	log.Println("Derleme Başladı")
	process_cmd(pkg.build,true,true,false)
	log.Println("Derleme Bitti")
}

func install_package(pkg *Talimat) {
	log.Println("Paket Kurma Başladı")
	process_cmd(pkg.install,true,true,false)
	log.Println("Paket Kurma Bitti")
}

func generate_package(pkg *Talimat) {
	log.Println("Paket Hazırlama Başladı")
	os.Chdir(pkgdir)
	pack_t := "%s#%s-%s-%s.mps"
	p_archive := fmt.Sprintf(pack_t, pkg.name, pkg.version, pkg.release, "x86_64")
	process_cmd(fmt.Sprintf("tar --preserve-permissions -cf %s * .meta .icbilgi",p_archive),true,true,false)
	// lzip -9 ${urpkt}.mps
	//process_cmd("lzip -9 "+p_archive,true,true,false)
	process_cmd("lzip -9 "+p_archive,true,true,false)
	// paketi taşı
	process_cmd("mv "+p_archive+".lz "+CurDir,true,true,false)
	log.Println("Paket Hazırlama Bitti")
}

func generate_package_info(pkg *Talimat) {
	log.Println("Paket Bilgisi Üretme Başladı")
	os.Chdir(CurDir)
	pack_t := "%s#%s-%s-%s.mps.lz"
	info_t := "%s %s %s %s %d %s %s"
	p_archive := fmt.Sprintf(pack_t, pkg.name, pkg.version, pkg.release, "x86_64")
	hash_val := process_cmd("sha256sum "+p_archive,false,false,true)
	hash_val = strings.Fields(hash_val)[0]
	pack_file, _ := os.Stat(p_archive)
	//pack_dir, _ := os.Stat(pkgdir)
	size := pack_file.Size()
	size_dir := process_cmd("du -sb "+pkgdir,false,false,true)
	size_dir = strings.Fields(size_dir)[0]
	f, _ := os.Create(p_archive+".bilgi")
    defer f.Close()
    f.WriteString(fmt.Sprintf(info_t, pkg.name, pkg.version, pkg.release, "x86_64", size, size_dir, hash_val))
    // pktlibler, libgerekler
    //process_cmd("cp "+pkgdir+"/.meta/libgerekler "+pkg.name+".libgerekler",true,true,false)
    //process_cmd("cp "+pkgdir+"/.meta/pktlibler "+pkg.name+".pktlibler",true,true,false)
	copy_file(pkgdir+"/.meta/libgerekler",pkg.name+".libgerekler")
	copy_file(pkgdir+"/.meta/pktlibler",pkg.name+".pktlibler")
	log.Println("Paket Bilgisi Üretme Bitti")
}

func copy_scripts(pkg *Talimat) {
	log.Println("Paket Koşuk Kopyalama Başladı")
	os.Chdir(pkgdir)
	cmd_str := "cp %s %s"
	scrpath := ""
	for _, script := range []string{"kurkos.sh","koskur.sh","silkos.sh","kossil.sh"} {
		// script file exists
		scrpath = pkg.tdir+"/"+script
		if _, err := os.Stat(scrpath); err == nil {
			process_cmd(fmt.Sprintf(cmd_str,scrpath,".meta/."+strings.Split(script,".")[0]),true,true,false)
		}
	}
	log.Println("Paket Koşuk Kopyalama Bitti")
}

func generate_mtree() {
	log.Println("Paket İçbilgi Başladı")
	os.Chdir(pkgdir)
	cmd_str := "bsdtar --preserve-permissions --format=mtree --options='!all,use-set,type,uid,gid,mode,time,size,sha256,link' -czf - * .meta > .icbilgi"
	process_cmd(cmd_str,true,true,false)
	log.Println("Paket İçbilgi Bitti")
}

func generate_meta(pkg *Talimat) {
	log.Println("Paket Meta Başladı")
	metadir := pkgdir + "/.meta/"
	os.Chdir(pkgdir)
	os.MkdirAll(metadir, 0755)
	
	f, err := os.Create(metadir + ".ustbilgi")
    check(err)
    defer f.Close()
    // boyut
    //pkgdir_boyut := process_cmd(fmt.Sprintf("du -sb %s",pkgdir),true,false,true)
    size_dir := process_cmd("du -sb "+pkgdir,false,false,true)
	size_dir = strings.Fields(size_dir)[0]
	thash := process_cmd("sha256sum "+pkg.tdir+"/talimat",false,false,true)
	thash = strings.Fields(thash)[0]
	w := bufio.NewWriter(f)
	metainfo := fmt.Sprintf(`isim=%s
surum=%s
devir=%s
tanim=%s
url=%s
paketci=%s
derzaman=1671887877
mimari=x86_64
grup=%s
boyut=%s
thash=%s
	`, pkg.name, pkg.version, pkg.release, pkg.desc, pkg.url, pkg.packager, pkg.group, size_dir, thash)
    _, err = w.WriteString(metainfo)
    check(err)
    w.Flush()
    
	log.Println("Paket Meta Bitti")
}

func generate_libs() {
	log.Println("Paket Kütüphane Oluşturma Başladı")
	os.Chdir(pkgdir)
	// pktlibler
	var lines []string
	lg_out := ""
	filepath.Walk("usr/",
	func(path string, file os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		// dosya işlemleri
		if !file.IsDir() {
			elft := elf_check(path)
			if (elft == 2 || elft == 3) {
				if strings.Contains(path,".so.") || path[len(path)-3:] == ".so" {
					lines = append(lines,filepath.Base(path))
				}
				lg_out += process_cmd(fmt.Sprintf("objdump -x %s | grep NEEDED",path),false,false,true)
			} 
		}
		return nil
	})
	if len(lines) > 0 {
		file, _ := os.Create(pkgdir + "/.meta/pktlibler")
		defer file.Close()
		w := bufio.NewWriter(file)
		for _, line := range lines {
			fmt.Fprintln(w, line)
		}
		w.Flush()
	}
	// libgerekler
	lg_map := make(map[string]int)
	if lg_out != "" {
		for _, line := range strings.Split(lg_out,"\n") {
			if strings.Contains(line,"NEEDED") {
				lg_map[strings.Fields(line)[1]] = 0
			}
		}
	}
	file2, _ := os.Create(pkgdir + "/.meta/libgerekler")
	defer file2.Close()
	w2 := bufio.NewWriter(file2)
	for k, _ := range lg_map {
		fmt.Fprintln(w2, k)
	}
	w2.Flush()
	log.Println("Paket Kütüphane Oluşturma Bitti")
}

func elf_check(file string) int {
	
	f, err := os.Open(file)
	_elf, err := elf.NewFile(f)
	if err != nil {
	  //fmt.Println(file,"not elf")
	  return -1
	}
	//defer f.Close()
	// Read and decode ELF identifier
	var ident [16]uint8
	f.ReadAt(ident[0:], 0)
	check(err)
	f.Close()
	if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
		fmt.Printf("Bad magic number at %d\n", ident[0:4])
		return -1
	} else if _elf.Type == 2 {
		return 2
	} else if _elf.Type == 3 {
		return 3
	} else {
		return -1
	}
}

func strip_file(file string) {
	
	ret := elf_check(file)
	if ret == 2 {
		process_cmd("strip --strip-all "+file,true,true,false)
		//fmt.Println(file,"exe stripped")
	} else if ret == 3 {
		process_cmd("strip --strip-unneeded "+file,true,true,false)
		//fmt.Println(file,"shared obj stripped")
	} else {
		fmt.Println(file,"not stripped")
	}
	//process_cmd("strip --debug "+file,true,true,false)
}

func compress_manpage(file string) {
	if strings.Contains(file, "usr/share/man") {
		fmt.Printf("manpages:")
		cmd_str := "gzip -9 %s"
		cmd_str = fmt.Sprintf(cmd_str, file)
		process_cmd(cmd_str,true,true,false)
	}
}

func delete_file(file string) {
	e := os.RemoveAll(file)
	if e == nil {
		fmt.Println("deleted:",file)
	} else {
		log.Println("delete_error",file)
	}
}

func IsEmpty(name string) bool {
    f, err := os.Open(name)
    if err != nil {
        return false
    }
    //defer f.Close()
    // https://stackoverflow.com/questions/37804804/too-many-open-file-error-in-golang
    _, err = f.Readdirnames(1) // Or f.Readdir(1)
    f.Close()
    if err == io.EOF {
        return true
    }
    return false
}

func process_files() {
	log.Println("Paket Dosya Düzenleme Başladı")
	os.Chdir(pkgdir)
	log.Println("-geçersiz dizinlerin kontrolü")
	name_checks := strings.Split(cfg.Section("files").Key("invalid").String(),",")
	for _, fd := range name_checks {
		if isDir(fd) {
			log.Fatal("geçersiz dizin:",fd)
		}
	}
	log.Println("-gereksiz dizinlerin silinmesi")
	delete_files := strings.Split(cfg.Section("files").Key("delete").String(),",")
	for _, fd := range delete_files {
		if isDir(fd) {
			delete_file(fd)
		}
	}
	// builtin silme betiği?
	if isDir("usr/lib") {
		process_cmd(`find usr/lib -name "*.la" ! -path "usr/lib/ImageMagick*" -exec rm -fv {} \;`,true,true,false)
	}
	// dosyaların strip
	// nostrip dosyası varsa strip pas geçilecek
	if _, err := os.Stat(pkgdir + "/nostrip"); err == nil {
		log.Println("-ikili ve paylaşımlı kütüphane tırpanı yapılmayacak")
	} else {
		log.Println("-ikili ve paylaşımlı kütüphane tırpanı")
		filepath.Walk(".",
		func(path string, file os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			// dosya işlemleri
			// dşizin ve kısayol değilse
			if !file.IsDir() && file.Mode().String()[0:1] != "L" {
				//fmt.Println("f----------",file.Mode())
				strip_file(path)
			}
			return nil
		})
	}
	/*
	log.Println("-manpages sıkıştırma")
	filepath.Walk("usr/share",
	func(path string, file os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !file.IsDir() {
			compress_manpage(path)
		}
		return nil
	})
	*/
	/*
	log.Println("-boş dizinlerin silinmesi")
	filepath.Walk(".",
	func(path string, file os.FileInfo, err error) error {
		if file.IsDir() {
			//fmt.Println("d----------",path)
			if IsEmpty(path) {
				delete_file(path)
			}
		}
		return nil
	})
	*/
	log.Println("Paket Dosya Düzenleme  Bitti")
}

func main() {
    build_sections = make(map[string]string)
    build_sections["derle"]="build" 
    build_sections["pakur"]="install" 
    var err error
    ini_path := "./mpsd.ini"
    if _, err := os.Stat(ini_path); err != nil {   
		ini_file := "/go/mpsd.ini"
		if _, mps_pf := os.LookupEnv("MPS_PATH"); mps_pf {
			ini_path = os.Getenv("MPS_PATH") + ini_file
		} else {
			ini_path = "/usr/milis/mps" + ini_file
		}
	}
    cfg, err = ini.Load(ini_path)
    if err != nil {
        fmt.Printf("mpsd.ini okunamadı: %v", err)
        os.Exit(1)
    }
    CurDir, _ = os.Getwd()
    prepare_env()
    create_dirs()
    
    // talimat dizin parametresi - tam yol tespiti
    talimat_dir, _ := filepath.Abs(os.Args[1])
    // talimat dosya yolu
    talimat_file := talimat_dir+"/talimat"
    // log ile yolun doğrulanması
    log.Println(talimat_dir,"işlenecek")
    if _, err := os.Stat(talimat_file); err != nil { 
		fmt.Printf("talimat dosyası bulunamadı: %v\n", talimat_file)
        os.Exit(1)
	}
	
	mpsd_mode := "-b" 
	if len(os.Args) > 2 {
		// -i parametresi beklenmekte
		// mpsd abc#1.2.3-1 -i
		// todo: çoğul mod desteği verilecek
		mpsd_mode = os.Args[2]
	}
    
    talimat, err := ini.LoadSources(
    ini.LoadOptions{
		AllowShadows: true, 
		IgnoreInlineComment: true,
		UnparseableSections: []string{"derle","pakur"},
	}, talimat_file)
	
    if err != nil {
        fmt.Printf("Fail to read file: %v", err)
        os.Exit(1)
    }
	
	var pkg *Talimat 
	pkg = new(Talimat) 
    pkg.tdir = talimat_dir
    
    // ayrıştırma
    parse_headers(talimat, pkg)
    prepare_pkg_env(pkg)
    parse_sources(talimat, pkg)
    parse_hashes(talimat, pkg)
    parse_build(talimat, pkg,"derle")
    parse_build(talimat, pkg,"pakur")
    
    // loglama
    log_file, err = os.Create(fmt.Sprintf("%s_%s-%s.log", pkg.name, pkg.version, pkg.release))
    check(err)
    mw := io.MultiWriter(os.Stdout, log_file)
    log.SetOutput(mw)
	
	// yazdırma
	pkg.Print()
	
	// talimat işleme
	if mpsd_mode == "-b" {
	fetch_sources(talimat, pkg)	
	check_sources(talimat, pkg)
	extract_sources(talimat, pkg)	
	build_package(pkg)
	mpsd_mode = "-i"
	}
	if mpsd_mode == "-i" {
	install_package(pkg)
	process_files() // strip + manpages + delete
	generate_meta(pkg)
	copy_scripts(pkg)
	generate_mtree()
	generate_libs()
	generate_package(pkg)
	generate_package_info(pkg)
	}
}
