#!/usr/bin/env slua
-- mps slua kodlaması

local milispath=os.getenv("MILIS_PATH")
if not milispath then milispath="/usr/milis" end

local talimatname=os.getenv("TALIMATNAME")
if not talimatname then talimatname=milispath.."/".."talimatname" end

local mps_path=os.getenv("MPS_PATH")
if not mps_path then mps_path=milispath.."/".."mps" end

local l5 = require("l5")
package.path  = mps_path.."/lua/?.lua"    .. ";".. package.path
package.path  = mps_path.."/lang/?.lua"   .. ";".. package.path
package.path  = mps_path.."/conf/?.lua"   .. ";".. package.path

local argparse = require ("argparse")
local color = require ("ansicolors")
local t=require ("talimat")

local util={}
util.renkli=true
local shell_log="/tmp/mps_helper-shell.log"
local static=mps_path.."/static/"
local busybox=static.."busybox "
--local busybox="/usr/bin/busybox "

-- harici komut tanımları
local cmd={
	lzip=function (paket) return (static.."lzip -d -k %s"):format(paket) end,
	tarx=function (arsiv,hedef) return (static.."tar xf %s -C %s"):format(arsiv,hedef) end,
	gzipd=function (arsiv) return (busybox.."gzip -dc %s"):format(arsiv) end,
	copy=function (kaynak,hedef) return (busybox.."cp -af %s %s"):format(kaynak,hedef) end,
	remove=function (dosya) return (busybox.."rm -rf %s"):format(dosya) end,
	mkdir=function (dizin) return (busybox.."mkdir -p %s"):format(dizin) end,
	readlink=function (dosya) return (busybox.."readlink -f %s"):format(dosya) end,
	xargs=function (komut) return (busybox.."xargs -I {} %s {}"):format(komut) end,
	dirname=function (dosya) return (busybox.."dirname %s"):format(dosya) end,
	basename=function (dosya) return (busybox.."basename %s"):format(dosya) end,
	chmodx=function (dosya) return (busybox.."chmod +x %s"):format(dosya) end,
	head=function (sira) return (busybox.."awk 'NR==1 {print}'"):format(sira) end,
	sed=function (ayar) return (busybox.."sed %s"):format(ayar) end,
	move=function (kaynak,hedef) return (busybox.."mv %s %s"):format(kaynak,hedef) end,
	http_code=function (link) return (static.."curl -ILs %s"):format(link) end,
	http_body=function (progress,link) return (static.."curl %s -L %s"):format(progress,link) end,
	cut=function (bol,sira) return (busybox.."cut -d'%s' -f%s"):format(bol,sira) end,
	sha256sum=function (hash,dosya) return (busybox..'echo "%s  %s" | '..busybox..'sha256sum -c ;[ $? -eq 1 ] && printf "err@r"'):format(hash,dosya) end,
	grep=function (param,ayar,yol) 
			if ayar ~= "" then 
				ayar=ayar:gsub("+","\\+")
				ayar='"'..ayar..'"'
			end	
			return (static..'rg %s %s %s'):format(param,ayar,yol) 
		end,
	paste=function (ayrac,ayar) return (busybox..'paste -d"%s"  %s'):format(ayrac,ayar) end,
	awk=function (param,ayar) return (busybox.."awk %s '%s'"):format(param,ayar) end,
	cat=function (dosya) return (busybox.."cat %s"):format(dosya) end,
	cat2=function (dosya,dosya2) return (busybox.."cat %s %s"):format(dosya,dosya2) end,
	sortp=function () return busybox.."sort" end,
	uniq=function (param) return (busybox.."uniq %s"):format(param) end,
	ls=function (param,dosya) return (busybox.."ls %s %s"):format(param,dosya) end,
	diff=function (dosya1,dosya2) return (busybox.."diff %s %s"):format(dosya1,dosya2) end,
	pipe=function(...) 
			local pc=""
			 for i,ar in ipairs({...}) do
				pc=pc..ar
				if i ~= #{...} then pc=pc.." | " end
			 end
			 return pc
		 end, 
}

-- cmd kısaltma
local xdirname=cmd.xargs(cmd.dirname(""))
local xbasename=cmd.xargs(cmd.basename(""))

-- yaz = farklı tipte çıktıları ekrana renkli yazan işlev
-- codes: 0=error, 1=success, 2=info 3=warning
getmetatable("").__index.yaz = function(msg,code)
	--print("*",msg,code,color)
	tip={'%{red}','%{green}','%{blue}','%{lred}'}
	if code == nil then code=2 end
	if util.renkli then
		--print(tip[code+1](msg))
		print(color(('%s%s'):format(tip[code+1],msg)))
	else
		print(msg)
	end
	if code == 0 then
		os.exit()
	end
end

--split string
function string:split(delimiter)
  local result = {}
  if delimiter == "." then  
    for i in string.gmatch(self, "[^%.]+") do
	  table.insert(result,i)
    end
  else
    local from  = 1
    local delim_from, delim_to = string.find( self, delimiter, from  )
    while delim_from do
      table.insert( result, string.sub( self, from , delim_from-1 ) )
      from  = delim_to + 1
      delim_from, delim_to = string.find( self, delimiter, from  )
    end
    table.insert( result, string.sub( self, from  ) )
  end
  return result
end

function string:run(log)
	-- Open log file in append mode
	if log ~= "log" then
		local logger = io.open(shell_log, "a")
		logger:write(self.."\n");
		logger:close();
	end
	
	local handle=io.popen(self)
	local result=handle:read('*all')
	handle:close()
	-- komut çıktısı sonu yeni satır karakterin silinmesi - en sondaki \n
	if result:sub(-1) == "\n" then
		--result=result:gsub("\n", "")
		result=result:sub(1,-2)
	end
	return result
end

-- check a variable in an array 
-- todo!!!  has_value kullanilan islevler find ile revize edilecek
function util.has_value (tab, val)
    for _, value in ipairs(tab) do
        if value == val then
            return true
        end
    end
    return false
end

-- get the index of an item in a table
function util.find(tab, val)
    for index, value in pairs(tab) do
        if value == val then
            return index
        end
    end
    return -1
end

-- print elements of a table-array
function util.tprint(tablo)
    for _, value in ipairs(tablo) do
       print (value)
    end
end

function shell(command,log)
	-- Open log file in append mode
	if log ~= "log!" then
		local logger = io.open(shell_log, "a")
		logger:write(command.."\n");
		logger:close();
	end
	
	local handle=io.popen(command)
	local result=handle:read('*all')
	handle:close()
	-- komut çıktısı sonu yeni satır karakterin silinmesi - en sondaki \n
	if result:sub(-1) == "\n" then
		--result=result:gsub("\n", "")
		result=result:sub(1,-2)
	end
	return result
end

-- get content of a file
function util.get_content(filename)
	assert(l5.lstat3(filename),"util.get_content : invalid path: "..filename)
	local f = assert(io.open(filename, "r"))
	local t = f:read('*all')
	f:close()
	return t
end

-- check a file has a line
function util.has_line(filename,line)
	assert(l5.lstat3(filename),"util.has_line : invalid path: "..filename)
	local cnt=util.get_content(filename)
	for linein in cnt:gmatch("[^\r\n]+") do 
		if linein == line then
			return true
		end
	end
	return false
end

-- check sha256sum of a file
function util.hash_check(filepath,hash_value)
	assert(l5.lstat3(filepath),"util invalid path: "..filepath)
	--local komut='busybox echo "%s  %s" | busybox sha256sum -c ;[ $? -eq 1 ] && printf "err@r"'
	--local ret=shell(komut:format(hash_value,filepath))
	local ret=cmd.sha256sum(hash_value,filepath):run()
	if ret:match("err@r") then
		return false
	end
	return true
end

-- convert byte to kilobyte,megabyte
function util.byte_convert(value)
	--test
	if value == "@test" then
		assert(util.byte_convert(1023) == "1023 B")
		assert(util.byte_convert(1025) == "1.0 KB")
		assert(util.byte_convert(1024*1025) == "1.00 MB")
		assert(util.byte_convert(1024*1025*1024) == "1.001 GB")
		return 1
	end
	
	local _kb=1024
	local _mb=1024*_kb
	local _gb=1024*_mb
	local result=""
	
	if type(value) == "string" then value=tonumber(value) end
	
	if     value > _gb then result=("%.3f GB"):format(value/_gb)
	elseif value > _mb then result=("%.2f MB"):format(value/_mb)
	elseif value > _kb then result=("%.1f KB"):format(value/_kb)
	else   result=("%.0f B"):format(value) end
	
	return result
end

local has_value=util.has_value
local find=util.find
local get_content=util.get_content
local has_line=util.has_line
local tprint=util.tprint
local hash_check=util.hash_check
local byte_convert=util.byte_convert


-- dil tespiti
local _langenv=os.getenv("LANG")
local def_lang="en"
if not _langenv then _langenv="en_US" end
local _langvar,_=_langenv:match("(.*)_(.*)")
local status_lang, messages = pcall(require, "lang_".. _langvar)
if not status_lang then
    messages = require ("lang_"..def_lang)
end
--------------------------------------------------

function stat(path) 
	return l5.lstat3(path)
end

-- mps ile ilgili ayarların conf/conf.lua dan yüklenmesi
if not stat(mps_path.."/conf/conf.lua") then
	cmd.copy(mps_path.."/conf/conf.lua.sablon", mps_path.."/conf/conf.lua"):run()
	messages.default_configs_loaded:yaz(2)
	messages.relaunch_mps:yaz(2)
	os.exit()
end
local ayar= require ("conf")
-------------------------------------------------------

-- Genel işlevler

function getcwd()
	return l5.getcwd()
end

function chdir(path)
	return l5.chdir(path)
end

function isdir(file)
	local dh,eno=l5.opendir(file)
	if dh then
		return true
	end
	return nil
end

function link(source,target) 
	if not stat(source) then exit(source.." is not exist") end 
	return l5.symlink(source,target) 
end

function mkdir(path,mode) 
	if not mode then mode=775 end 
	return l5.mkdir(path,tonumber(tostring(mode),8)) 
end

function get_size(path)
	local _,size,_ = stat(path)
	return size
end

function rmdir(path) 
	return l5.rmdir(path)
end

function http_request(link,progress)
	local pb="-s"
	if progress == "progress" then
		pb="--progress-bar"
	end
	local code=cmd.http_code(link):run()
	local body=""

	if code:match("200") then 
		body=cmd.http_body(pb,link):run()
		return body,"200"
	elseif code:match("404") then
		return body,"404"
	else
		return body,"can't connect"
	end
end

-- DIZIN OLUŞTURMA - KONTROL --

-- Paketleme dizini, yürürlük dosyasının oluşturulduğu konum
local paketleme_dizin=os.getenv("PAKETLEME_DIZIN")
if not paketleme_dizin then paketleme_dizin=getcwd() end

local islem={}
islem.api={}

-- local talimatname="/usr/milis/talimatname"
local kokdizin=""

local paket_arsiv_pattern="([%a%d-_+]+)#([%d%a.]+)-([%d]+)-([%a%d_]+)" -- paket_isim#surum-devir-mimari : abc#1.2.3-1-x86_64
-- paket arşiv format -paket_isim#surum-devir-mimari.mps.lz
local paf="%s#%s-%s-%s.mps.lz"
-- paket gösterim formatı
local pgf="%s#%s-%s"
-- paket depo link formatı - depo_adres/paket_isim#surum-devir-mimari.mps.lz / paf kullan
local plf="%s/%s"

local rotator_sym={"\\","/"}

-- GLOBAL İŞLEVLER

-- genel parametre inceleme ve düzenlenmesi
function args_handler()
  -- parametrelere dönük özel işler yapılır.
  color_check()
  rootfs_check()
  --mps init kontrolü
  if args.ilk    then mps_init()   end
  if args.ilkds then mps_initfs() end
  
  local komut_islev={["in"]="indir",der="derle",kur="kur",
				sil="sil",gun="guncelle",ara="ara",
				sor="sorgu",bil="bilgi",kos="kos"}
  
  if args.command then
	local islev=komut_islev[args.command]
	if islev then
		if islem[islev] then
			islem[islev]["handler"](args)
		else
			print("not implemented yet")
		end
	--islem[args.command]["handler"](args)
	else
		print("not implemented yet")
	end
  end
end

-- root yetkili kontrolü
function authorised_check()
	if not os.getenv("MPS_NOROOT") then
		local me=os.getenv("USER")
		if me ~= "root" then
			messages.need_root:yaz(0)
		end
	end
end

-- parametre analiz/ color option check
function color_check()
	if args.renk == "0" then util.renkli=false end
	if args.renk == "1" then util.renkli=true end
end

-- parametre analiz/ package management root check
function rootfs_check()
	if args.kok:sub(-1) ~= "/" then args.kok=args.kok.."/" end
	kokdizin=args.kok
end

function mps_init()
	-- mps için gerekli dizinlerin oluşturulması
	-- /var/lib/mps/db
	cmd.mkdir(kokdizin.."tmp"):run()
	cmd.mkdir(kokdizin..islem.paket.vt):run()
	cmd.mkdir(kokdizin..islem.paket.logdir):run()
	cmd.mkdir(kokdizin..islem.kur.logdir):run()
	cmd.mkdir(kokdizin..islem.sil.logdir):run()
	cmd.mkdir(kokdizin..islem.paket.cachedir):run();
	(messages.init_is_ok..kokdizin):yaz()
end


-- mps dosya sistemi ilkleme
function mps_initfs()
	-- Milis için gerekli dizinlerin oluşturulması
	local initfs_komut=("bash %s/conf/init_rootfs.sh %s"):format(mps_path,kokdizin)
	initfs_komut:run();
	--print(initfs_komut);
	(messages.initfs_is_ok..kokdizin):yaz()
end

-- Diyalog İşlemleri

islem.diyalog={}

function islem.diyalog.onay(mesaj)
	local answer="-"
	if mesaj == nil then mesaj="?(y/n)" end
	repeat
	io.write(mesaj)
	io.flush()
	answer=io.read()
	until answer=="y" or answer=="n" or answer=="e" or answer=="h"
	if answer=="y" or answer=="e" then return true
	else return false end
end

-- MPS İŞLEMLER

-- talimat bul
islem.talimat_bul={
	retkey="talimat_bul:",
}

function islem.talimat_bul.job(paket,hepsi)
	-- alfanumerik arama yapılır.
	-- 2.parametere tip=hepsi gönderilirse bütün arama sonuçları çevirilir.
	--local komut=('busybox find %s -name "%s#*" | busybox sort -n | busybox head -1'):format(talimatname,paket)
        --  "rg --sort path --files %s -g talimat | rg '/%s#'"
	local komut=cmd.grep("--sort path --files","",talimatname).." -g talimat"
        local ret=""

	if hepsi=="1" then
		ret=cmd.pipe(komut,cmd.grep("",paket,""),xdirname):run()
	else
		ret=cmd.pipe(komut,cmd.grep("",'/'..paket..'#',""),xdirname,cmd.head()):run()
	end
	
	if ret == "" then
		return false
	else
		return ret
	end
end

islem.ara={usage="",}

-- talimat bulma işlevi (mps bul talimat_isim)
function islem.ara.handler(input)
	local hepsi = input.hepsi
	local arlist={}
	
	-- konsoldan girilen paket girdi analiz
	if input.arama then
		for _,pk in ipairs(input.arama) do table.insert(arlist,pk) end
	end
	
	-- arama test işlevi
	if input.test then
		for _,pk in ipairs(arlist) do print("ar",pk) end
	end
	
	local ret=""	
	for _,arama in ipairs(arlist) do
		-- talimat araması ise
		if input.talimat then
			ret=islem.talimat_bul.job(arama,hepsi)
			if ret then print(ret)
			else messages.talimat_not_found:yaz(0)
			end
		-- tanım araması ise
		elseif input.tanim then
			--local kom='rg "^tanim*" %s |busybox sed \'s/\\/talimat:tanim//\' | rg -i "%s"'
			local komut=cmd.pipe(cmd.grep("","^tanim*",talimatname),cmd.sed("\'s/\\/talimat:tanim//\'"),cmd.grep("-i",arama,""))
			--print(kom:format(talimatname,arama))
			ret=komut:run()
			if ret and ret ~= "" then print(ret) 
			else print(messages.desc_not_found:format(arama))
			end
		-- parametre belirtilmediyse öntanımlı olarak paket araması uygulanır.
		else
			-- 2021-12 çoklu paket.vt ile denenecek
			-- sürüm-devir eklenecek
			local kom=cmd.grep("-iN -g paket.vt#*",arama, kokdizin..islem.paket.cachedir)
			kom=cmd.pipe(kom,cmd.cut('#',2),cmd.cut(' ',"1-3"),"column -t")
			ret=kom:run()
			if ret and ret ~= "" then print(ret) 
			else print(messages.package_not_found:format(arama))
			end
		end
	end
end

--

-- Kaynak işlemleri
-- kaynak talimatın içerdiği kaynakları gösterecek
-- todo!!! bil altına alınacak
-- todo!!! talimat.lua ya göre güncel

islem.kaynak={
	usage="mps kaynak talimat_ismi",
	kontrol=false,
}

function islem.kaynak.handler(input)
	local liste={}
	if #input > 1 then
		-- 1 is talimat_bul işlemi
		local _islem=input[1]
		local girdi=input[2]
		local param=input[3]
		local dosya = girdi:match("^-%-dosya=(.*)$")

		if param and param:match("--kontrol") then islem.kaynak.kontrol=true end
		if dosya then
			if stat(dosya) then
				islem.kaynak.liste_dosyadan(dosya)
			else
				messages.file_not_found:format(dosya):yaz(0)
			end
		else
			-- girdi parametresi talimat olarak değerlendirelecek.
			local ret=islem.talimat_bul.job(girdi)
			if ret then
				-- kaynaklar kontrol edilecekse
				if islem.kaynak.kontrol then
					islem.kaynak.url_kontrol(islem.kaynak.liste(ret))
				-- kontrol yoksa sadece listeleme
				else
					tprint(islem.kaynak.liste(ret))
				end
			else
				messages.talimat_not_found:yaz(0)
			end
		end
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end

-- talimata ait kaynakların listelenme işlevi
function islem.kaynak.liste(talimatd)
	assert(stat(talimatd),"talimat dizin not found!")
	local talimatf=talimatd.."/talimat"
	assert(stat(talimatf),talimatf.." file not found!")
	-- talimat dosyasından alınan kaynaklar bash ile yorumlanıp
	-- açık değerlerine çevirlecektir.
	local kliste={}
	local talimat=t.get(talimatd)
	local komut='url=%s && isim=%s && surum=%s && devir=%s && echo '
	komut=komut:format(talimat.paket.url,talimat.isim,talimat.surum,talimat.devir)
	for _,val in ipairs (t.kaynaklar(talimat)) do
		table.insert(kliste,(komut..val):run())
	end
	return kliste
end

-- dosyadaki talimata ait kaynakların listelenme işlevi
function islem.kaynak.liste_dosyadan(dosya)
	local ret=nil
	for pk in (get_content(dosya)):gmatch("[^\r\n]+") do
		ret=islem.talimat_bul.job(pk)
		if ret then
			-- kaynaklar kontrol edilecekse
			if islem.kaynak.kontrol then
				islem.kaynak.url_kontrol(islem.kaynak.liste(ret))
			-- kontrol yoksa sadece listeleme
			else
				tprint(islem.kaynak.liste(ret))
			end
		else
			messages.talimat_not_found:yaz(0)
		end
	end
end

-- talimata ait kaynakların url aktif kontrolü
function islem.kaynak.url_kontrol(kaynaklar)
	local komut="%s -q --spider %s && echo $?"
	local ret=""
	for _,kaynak in ipairs(kaynaklar) do
		if kaynak:match("http") or kaynak:match("https") then
			ret=komut:format(wget_prog,kaynak):run()
			if ret == "0" then
				print(kaynak, "OK")
			else
				print(kaynak, "NOT")
			end
		else
			print(kaynak, "PASS")
		end
	end
end


-------

---------- Gerekler İşlemler ----------

islem.gerek={
	retkey="gerek:",
	usage="mps gerek paket_ismi tip",
	-- aktif gerek listesi
	liste={},
	-- aktif gereklerin eklenme kontrol listesi
	list={},
	sh_list={},
}

function islem.gerek.job(talimatd,tip)
	assert(talimatd,"talimatd is nil!")
	local talimat=t.load(talimatd.."/talimat",{"derle","pakur","kaynak"})
	--todo!!! sonsuz gerek döngüsü engellenecek.
	-- gereklerin toplanan listeye eklenmesi
	-- işlem yapıldığına dair imleç hareketi
	io.write(rotator_sym[ math.random( #rotator_sym) ].."\b")
    	io.flush()
	
	local function ekle(talimatd)
        	tisim = cmd.basename(talimatd:split("#")[1]):run()
                if islem.gerek.list[tisim] == nil then
                        islem.gerek.list[tisim]=talimatd
                        --print("e",talimatd)
                        table.insert(islem.gerek.liste,talimatd)
                end
        end

	-- talimatın libgerekler dosyasının analiz edilmesi
	local function oto_rdeps(talimatd)
		if stat(talimatd.."/"..islem.shlib.dosya) then
			local sh_tal=""
			local shlibs=get_content(talimatd.."/"..islem.shlib.dosya)
				for sh in shlibs:gmatch("[^\r\n]+") do
					--sh_tal=islem.shlib.bul(sh,"-t","ilk")
					if islem.gerek.sh_list[sh] then
						sh_tal=islem.gerek.sh_list[sh]
						--print(sh,sh_tal,"cache")
					else
						sh_tal=islem.shlib.bul(sh,"-t","ilk")
						if not sh_tal then sh_tal=0 end
						islem.gerek.sh_list[sh]=sh_tal
						--print(sh,sh_tal,"once")
					end
					if sh_tal and sh_tal ~= talimatd and sh_tal ~= 0 then
						--print("3",sh_tal)
						islem.gerek.job(sh_tal,"c")
					end
				end
		end
	end

	-- alt gereklerin dolaşılması
	local function gerek_dolas(dep,talimatd)
		local _td=islem.talimat_bul.job(dep)
		-- bir önceki paketin kurulabilir değeri iptal ediliyor
		local kurulabilir=false
		if _td then
			-- bir paketin depodaki bulunma durumuna göre
			-- derleme ve çalışma gereklerinin araştırılması yapılmaktadır.
			-- çalışma gerek araşırılmasında da aynı durum kontrol edilmektedir.
			-- todo!!! alt işleve alınacak alttaki operasyon
			tsd=cmd.basename(_td):run()
			for _,b in ipairs(islem.paket.pkvt_bilgi(dep)) do
				pksd=pgf:format(b.isim,b.surum,b.devir)
				if tsd == pksd then
					kurulabilir=b
					break
				end
			end
			if kurulabilir then
				tip="c"
			else
				tip="d"
			end

			islem.gerek.job(_td,tip)
		else
			(messages.talimat_not_found..talimatd..":"..dep):yaz(0)
		end
	end
	-- ikincil dolasma engelleme
	tisim = cmd.basename(talimatd:split("#")[1]):run()
	if islem.gerek.list[tisim] == nil then
		-- talimatdaki gerek kısmının analiz edilmesi - ana iskelet
		if talimat["gerek"] then
			local rdeps=talimat["gerek"]["calisma"]
			local bdeps=talimat["gerek"]["derleme"]
			local kurulabilir=false
			if tip == "d" and bdeps then
				for dep in bdeps:gmatch('([^%s]+)') do
					gerek_dolas(dep,talimatd)
				end
			elseif rdeps then
				for dep in rdeps:gmatch('([^%s]+)') do
					gerek_dolas(dep,talimatd)
				end
			end
			oto_rdeps(talimatd)
			ekle(talimatd)
		else
			oto_rdeps(talimatd)
			ekle(talimatd)
		end
	end

end

islem.tgerek={comment=messages.comment_mps_rev_dep,}

function islem.tgerek.job(paket, tip)
	print("Ters gerekler:");
	print("-------------------")
	local local_paketler={}
	--local dirbase1_cmd="busybox xargs -I {} busybox dirname {} | busybox xargs -I {} busybox basename {} | cut -d'#' -f1"
	--local tgkomut="busybox grep -r ' *%s *= *' %s | busybox grep ' %s$\\| %s \\|=%s$\\|=%s ' | busybox cut -d':' -f1 | "..dirbase1_cmd
	local paket_filter=cmd.grep("",(' %s$| %s |=%s$|=%s '):format(paket,paket,paket,paket),"")
	if tip == "d" then
		-- derleme
		ret=cmd.pipe(cmd.grep(""," *derleme *= *",talimatname),paket_filter,cmd.cut(':',1),xdirname,xbasename,cmd.cut('#',1)):run()
		for line in ret:gmatch("[^\r\n]+") do
			table.insert(local_paketler, line)
		end
	else
		-- calistirma
		ret=cmd.pipe(cmd.grep(""," *calisma *= *",talimatname),paket_filter,cmd.cut(':',1),xdirname,xbasename,cmd.cut('#',1)):run()
		for line in ret:gmatch("[^\r\n]+") do
			table.insert(local_paketler, line)
		end
		-- libgerek dosyasindan
		local talimatd=islem.talimat_bul.job(paket)
		if stat(talimatd.."/".."pktlibler") then
			local sh_tal=""
			local shlibs=get_content(talimatd.."/".."pktlibler")
				for sh in shlibs:gmatch("[^\r\n]+") do
					-- 2021-12 sort edilecek
					--local komut=("rg -l '%s$' %s -g libgerekler | "..dirbase1_cmd):format(sh,talimatname)
					local komut=cmd.grep("--sort path -l -g libgerekler",sh..'$', talimatname)
					--sh_tal=shell(komut)			
					sh_tal=cmd.pipe(komut,xdirname,xbasename,cmd.cut('#',1)):run()
					for line in sh_tal:gmatch("[^\r\n]+") do
						if not has_value(local_paketler, line) then
							table.insert(local_paketler, line)
						end
					end
				end
		end
	end
	tprint(local_paketler)
	print("-------------------")
end

------------------------------------------

-- Derle işlemi

islem.derle={
	retkey="derle:",
	usage="mps derle paket_ismi",
}

function islem.derle.handler(input)
	local derlist={}
	
	local hedefkur=false
	if input.kur then
		hedefkur=true
	end
	
	local function pk_analiz(talimat)
		local _durum=islem.talimat_bul.job(talimat)
		if _durum then
			table.insert(derlist,talimat)
		else
			(messages.talimat_not_found..talimat):yaz(0)
		end
	end
	
	-- konsoldan girilen paket girdi analiz
	if input.paket then
		for _,pk in ipairs(input.paket) do pk_analiz(pk) end
	end
	
	-- dosya parametresi içerik girdi analiz
	if input.dosya then
		if stat(input.dosya) then
			for pk in (get_content(input.dosya)):gmatch("[^\r\n]+") do 
				pk_analiz(pk)
			end
		else	
			messages.file_not_found:format(dosya):yaz(0)
		end
	end
	
	-- derle test işlevi
	if input.test then
		for _,pk in ipairs(derlist) do print("d",pk) end
	else
		-- test yoksa derle işlemi yapacak
		for _,dpaket in ipairs(derlist) do
			if input.tek then
				islem.derle.tek(dpaket)
			else
				islem.derle.job(dpaket,hedefkur)
			end
		end
	end
end

function islem.derle.job(paket,hedefkur)
	--talimatın konumu bulunarak gelecek handler den
	local ret=islem.talimat_bul.job(paket)
	local retq=nil
	-- pk   = paket isim
	-- pksd = ağdaki paket sürüm-devir
	-- tsd  = talimat sürüm-devir
	-- ksd  = kurulu sürüm-devir
	local pk,pksd,tsd,ksd=""
	local derlet=false
	local kurulabilir=false
	local eski_sil=false

	-- derleme işlemi
	-- todo!!! mpsd.lua lib olarak çağrılacak sonra, şu an shell
	-- 1. Derleme gerekleri bul.
	islem.gerek.job(ret,"d")
	--tprint(islem.gerek.liste)
	-- 2. Döngüde gerekler incelenir.
	local pb={}
	local ksd=nil
	for _,talimatd in ipairs(islem.gerek.liste) do
		-- her gerekte derletme ve kurulma durumları sıfırlanacak.
		derlet=false
		kurulabilir=false
		-- 2.1 kurulu kontrol
		tsd=cmd.basename(talimatd):run()
		pk,_=tsd:match("([%a%d-_+]+)#+")
		
		-- kurulu kontrol , link dizin dönüşü ile
		if islem.paket.kurulu_kontrol(pk) then
			pb=islem.paket.kurulum_bilgileri(pk)
			ksd=pb.isim.."#"..pb.surum.."-"..pb.devir
		else
			ksd=nil
		end
		
		-- 2.1.1 paket kurulu ise sürüm-devir uyum kontrolü yapılır.
		if ksd then
			-- ksd kurulu yol, sadece talimat isim formatı
			--ksd=get_basename(ksd)
			if tsd ~= ksd then
				print("kurulu sürümd ile derlenmesi gereken sürümd farklı-derlenecek!")
				-- paket kurulu sd uyumsuzluğu var
				-- paketi sildir(onaylı?) ve derlet
				-- önemli !!!-eski paketi derleme başarılı olursa sildir.
				derlet=true
				eski_sil=true
			else
				messages.package_already_installed_and_uptodate:format(pk):yaz(2)
				goto continue
			end
		-- 2.1.2 paket kurulu değilse ağdan indirilip kurulacak
		end
		-- ağdaki paketin surumdeviri incelenecek
		-- tsd ile pksd karşılaştır
		-- paket.vt lerdeki paket sürüm-devir bilgileri taranacak.
		-- tsd e eşleşen bulunursa eşleşen! indirilecek yoksa derletilecek.
		-- pakete ait depolarda bulduğu pkvt bilgisini getirecek.
		for _,b in ipairs(islem.paket.pkvt_bilgi(pk)) do
			pksd=pgf:format(b.isim,b.surum,b.devir)
			if tsd == pksd then
				--print(pk,b.depo,"bulundu.")
				kurulabilir=b
				break
			end
		end
		-- kurulabilir nesnesine ağdaki paket bilgisi atılacak.
		if kurulabilir then
			-- paket önbellekte varsa
			-- shasum kontrolü yapılıp yerelden kurulma yapılacak.
			-- ağdan indirmeden önce önbellekte kontrol edecek
			local _pkt=paf:format(pk,kurulabilir.surum,kurulabilir.devir,kurulabilir.mimari)
			local kur_onay=false
			local _indir=false
			local _pktyol=kokdizin..islem.paket.cachedir.."/".._pkt
			if stat(_pktyol) then
				if hash_check(_pktyol,kurulabilir.shasum) == false then
					--delete file
					cmd.remove(pktyol):run()
					_indir=true
				end	
			else
			   -- önbellekte yoksa veya hash uyumsuzsa indirilecek
			   _indir=true
			end
			if _indir == true then
				islem.indir.handler({paket={pk}})
			end
			-- todo!!! paket önbellekte ise hash kontrolü yapılıyor - indikten sonra da yapılmalı.
			-- indirilememe veya herhangi bir nedenden paketin önbellekte hazır olmaması durumu
			if not stat(_pktyol) then
				messages.package_not_found:format(_pktyol):yaz(0)
			else
				-- ağdan inen veya önbellekteki paket kurulabilir
				-- ayrıca eski paket kurulu ise kaldırılacak.
				if eski_sil == true then
					print("eski sürüm paket tespit edildi, kaldırılacak")
					islem.sil.handler({paket={pk}})
				end
				--print(_pktyol,"kurulacak")
				islem.kur.yerelden(_pktyol)
				-- paket kurulduysa eğer eski sürümden dolayı onay verilen derletme
				-- işlemi iptal edilecektir.
				derlet=false
			end
		else
			derlet=true
		end

		-- 2.2 derleme
		if derlet == true then
			-- aktif oluşan paket arşiv
			local mimari=("uname -m"):run()
			local pkarsiv=tsd.."-"..mimari..".mps.lz"
			-- hedef paket isimleri
			local hpksd=cmd.basename(ret):run()
			local hdarsiv=hpksd.."-"..mimari..".mps.lz"
			-- 2.2.1 talimat derle
			print(talimatd,"tl derlenecek")
			local komut="%s/bin/mpsd %s 2>&1 | tee  %s.log"
			os.execute(komut:format(mps_path, talimatd, pk))
			-- 2.2.2 üretilen paketi kur
			-- hedef üretilmek istenen pakete gelindiğinde
			-- bu noktada derleme başarılı olup paket üretildiği
			-- kontrol edilerek eski sürüm paket kaldırılır.

			if pk == paket then
				-- mps derle paket --kur seçeneğine bakılacak.
				if hedefkur == true then
					-- hedef paket arşivi
					if stat(paketleme_dizin.."/"..hdarsiv) then
						if eski_sil then islem.sil.handler({paket={pk}}) end
						print(paket.." hedef paket de kurulacak.")
						islem.kur.yerelden(paketleme_dizin.."/"..hdarsiv)
					else
						messages.package_not_found:format(hdarsiv):yaz(0)
					end
				end
			else
				-- altgereklerin oluşan paketleri zorunlu kurulacak
				if stat(paketleme_dizin.."/"..pkarsiv) then
					if eski_sil then islem.sil.handler({paket={pk}}) end
					islem.kur.yerelden(paketleme_dizin.."/"..pkarsiv)
				else
					messages.package_not_found:format(pkarsiv):yaz(0)
				end
			end
		end
		::continue::
	-- for bitiş
	end
	--print(paket.." derleme bitti")
end

function islem.derle.tek(paket)
	--talimat konum bul
	ret=islem.talimat_bul.job(paket)
	if ret then
		print(ret.." derlenecek")
		local komut="%s/bin/mpsd %s 2>&1 | tee  %s.log"
		os.execute(komut:format(mps_path, ret, paket))
	else
		(messages.talimat_not_found..paket):yaz(0)
	end
end

------------------------------

-- Paket Arşiv işlemleri
islem.arsiv={
	retkey="arşiv:",
}

-- Milis paketi ön kontrolleri
function islem.arsiv.kontrol(paket)
	-- kullanıcı hedefli de çıktı verilebilinir.
	assert(stat(paket),"islem.arsiv.kontrol : paket is not found")
	assert(paket:match("mps.lz"),"islem.arsiv.kontrol : paket suffix is not mps.lz")
	assert(get_size(paket) ~=0,"islem.arsiv.kontrol : paket size equals zero")

	local isd = cmd.basename(paket):run()
	local isim,surum,devir,mimari=isd:match(paket_arsiv_pattern)
	if not (isim and surum and devir and mimari) then
		print(messages.valid_format..paf:format(isim,surum,devir,mimari));
		(messages.package_name_format_not_valid..isd):yaz(0)
	end
	-- bir kontrol de tar ile içeriden paket bilgi dosyası çekilebilir
	-- bu kontrol extract den sonra yapılabilir, aynı işlemi tekrarlamamak için
	--("arşiv_kontrol:\tOK"):yaz();
	islem.debug.yaz(messages.package_archive_check_ok)
	return isim,surum,devir
end

function islem.arsiv.tempdir(paket)
	-- paket arşivinin açılacağı temp dizin ayarlanması
	assert(paket,"islem.arsiv.tempdir : paket is nil")
	local tempdir=kokdizin.."tmp/"..cmd.basename(paket):run()..".tmpdir"
	assert(tempdir ~= "/tmp","islem.arsiv.tempdir : tempdir must not be /tmp")
	assert(tempdir ~= "/","islem.arsiv.tempdir : tempdir must not be /")
	-- paketin açılacağı tempdir oluşturma
	rmdir(tempdir)
	mkdir(tempdir)
	return tempdir.."/"
end

-- Milis paketi dışarı çıkarma/extract
function islem.arsiv.cikar(paket)
	-- ön kontrollerin yapıldığı varsayılıyor/handler func ile ?
	-- paketin açılması		
	local tempdir=islem.arsiv.tempdir(paket)
	local tar_file=paket:split("%.lz")[1]
	-- lzip çıkarma 
	cmd.lzip(paket):run()
	
	if not stat(tempdir) then
		mkdir(tempdir)
	end
	-- tar çıkarma
	cmd.tarx(tar_file,tempdir):run()
	cmd.remove(tar_file):run()
	
	-- arşiv çıkarılması test edilecek!!!
	-- gnu sparse kontrolü (https://www.gnu.org/software/tar/utils/xsparse.html)
	
	local log=messages.package_archive_extract_ok;
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")

	return tempdir
end
------------------------------

-- Shared Libs(Paylaşılan kütüphaneler) işlemleri

islem.shlib={
	retkey="shlib:",
	dosya="libgerekler",
}

--  -libbul
islem.api.libbul={
	usage="",
	comment="Bir .so dosyasını içeren paket veya talimatı bulur."
}
islem.api.libbul.job=function (params)
	local shlib=nil
	local param=params[2]
	if param == "-t" then
		shlib=params[3]
	else
		shlib=param
	end
	if shlib then
		print(islem.shlib.bul(shlib,param,"hepsi"))
	else
		messages.args_at_least_one:yaz(0)
	end
end


function islem.shlib.kontrol(tempdir)
	-- shlib kontrolü / altına kurulumlarda yapılabilir
	-- farklı bir kök altına kurulumlar için
	-- shlib dosya arama yoluyla olabilir.
	local log=""
	local ldconfig_bin="/usr/bin/ldconfig"
	if kokdizin == "/" and stat(ldconfig_bin) then
		assert(tempdir,"islem.shlib.kontrol : tempdir is nil")
		local shlibdos=tempdir..islem.paket.metadir..islem.shlib.dosya
		local pklibdos=tempdir..islem.paket.metadir..islem.paket.pktlib_dosya
		local iclib_kontrol=false
		if stat(pklibdos) then iclib_kontrol=true end
		if stat(shlibdos) and get_size(shlibdos) > 0 then
			local shlibs=get_content(shlibdos)
			for sh in shlibs:gmatch("[^\r\n]+") do
				if iclib_kontrol and has_line(pklibdos,sh) then
					log="shlib.kontrol\tOK";
				elseif not islem.shlib.exist(sh) then
					(messages.shlib_not_exits..sh):yaz(3)
				end
			end
		end
		log="shlib.kontrol\tOK";
		islem.debug.yaz(log);
		islem.kur.logger:write(log.."\n")
	else
		log="shlib.kontrol\tPASS";
		islem.debug.yaz(log);
		islem.kur.logger:write(log.."\n")
	end
end

function islem.shlib.exist(shlib)
	assert(shlib,"islem.shlib.exist : shlib is nil")
	local komut=cmd.pipe("ldconfig -p",cmd.grep("",shlib,"")).." > /dev/null;echo $?"
	--local komut='ldconfig -p | grep '..shlib..' | awk \'{split($0,a,"=> "); print a[2]}\' | xargs -r ls > /dev/null 2>&1;echo $?'
	ret=komut:run()
	assert(ret~="","islem.shlib.exist : ret is empty")
	--print (ret,komut)
	if ret == "0" then return true end
	return false
end

function islem.shlib.bul(shlib,param,show_opt)
	assert(shlib,"islem.shlib.bul : shlib is nil")
	--local opt=" | head -n1"
	local opt=cmd.head()
	if show_opt=="hepsi" then
		opt=""
	end
	if param=="-t" then
		--local komut=("busybox grep -r -i -l --include=\\%s '%s$' %s | xargs -I {} dirname {} %s "):format(islem.paket.pktlib_dosya,shlib,talimatname,opt)
		--local komut=("rg -l '%s$' %s -g %s"):format(shlib,talimatname,islem.paket.pktlib_dosya)
		local komut=cmd.grep("--sort path -l",shlib.."$",talimatname).." -g "..islem.paket.pktlib_dosya
		--ret=shell(komut,"log!")	
		--print(cmd.pipe(komut,xdirname,opt))
		ret=cmd.pipe(komut,xdirname,opt):run()
		if ret ~= "" then
			return ret
		end
	else
		-- todo!!! kurulu paketler için yapılacak
		return nil
	end
end
------------------------------

-- İçbilgi(mtree) işlemleri

-- içbilgi içindeki dosyaları yazdırmak
islem.api.ib={
	usage="",
	comment="",
}

islem.api.ib.job=function (params)
	local paket=params[2]
	local list,_=islem.icbilgi.dosyalar(kokdizin..islem.paket.vt..paket.."/")
	if next(list) then
		for _,dos in ipairs(list) do
			print(dos)
		end
	end
end

islem.icbilgi={
	retkey="icbilgi:",
	dosya=".icbilgi",
}

------------------Paket ve Veritabanı İşlemleri-----------------------

islem.paket={
	retkey="paket:",
	vt="var/lib/mps/db/",
	logdir="var/log/mps/",
	--cachedir="tmp",
	cachedir="var/cache/mps/depo",
	pktlib_dosya="pktlibler",
	ustbildos=".ustbilgi",
	metadir=".meta/",
}

------------------Bilgi  İşlemleri-----------------------

islem.bilgi={retkey="bilgi:",}

function islem.bilgi.job(info)
	-- todo!!!  kurulu paket ve talimatnamedeki talimat özbilgileri ayrılacak
	-- parametrelerle ayrılacak...
	-- bu işlev yeniden değerlendirilecek
	-- önce kurulu kontrol yapılıp kurulu ise yerel vt den bilgi alınacak.
	local isim,surum,devir,tanim,paketci,url,grup,mimari,aboyut,kboyut,durum=""
	-- todo!!! diğer durumlarda incelenebilir talimat, paketvt den bilgi alımı?
	if info.durum == "kurulu" then
		local kpb=islem.paket.kurulum_bilgileri(info.paket)
		isim,surum,devir,tanim=kpb.isim,kpb.surum,kpb.devir,kpb.tanim
		url,paketci,grup,mimari=kpb.url,kpb.paketci,kpb.grup,kpb.mimari
		kboyut=byte_convert(kpb.boyut)
		aboyut=nil
		if info.talimatdir == false then info.durum= info.durum.." (talimatı yok)" end
		durum=info.durum
	else
		--talimat ayrıştırıcı kullanılarak talimat bilgileri alınır.
		local talimat_dir=cmd.readlink(info.talimatdir):run()
		local isd=cmd.basename(talimat_dir):run()
		local input=t.load(talimat_dir.."/talimat",{"derle","pakur","kaynak"})
		
		input.paket.isim=isd:split("#")[1]
		input.paket.surum=isd:split("#")[2]:split("-")[1]
		input.paket.devir=isd:split("#")[2]:split("-")[2]
		-- genel değişken atamaları
		isim=input.paket.isim
		tanim=input.paket.tanim
		grup=input.paket.grup
		url=input.paket.url
		paketci=input.paket.paketci
		-- kurulu değil ise paket.vt'den bilgileri al
		local pbs = islem.paket.pkvt_bilgi(isim)
		-- todo!!! nil değer gelmeme kontrol edilecek
		--paket.vt dosyasindaki gerekli girdileri al
		local pb = pbs[1]
		if pb == nil then
			surum=input.paket.surum
			devir=input.paket.devir
		else
			aboyut=byte_convert(pb.aboyut)
			kboyut=byte_convert(pb.kboyut)
			surum=pb.surum
			devir=pb.devir
			mimari=pb.mimari
		end
		durum=messages.not_installed
	end
	print(("%-13s : %s"):format(messages.package_info_name,isim))
	print(("%-13s : %s"):format(messages.package_info_desc,tanim))
	print(("%-13s : %s"):format(messages.package_info_group,grup))
	print(("%-13s : %s"):format(messages.package_info_url,url))
	print(("%-13s : %s"):format(messages.package_info_packager,paketci))
	print(("%-13s : %s"):format(messages.package_info_version,surum))
	print(("%-13s : %s"):format(messages.package_info_release,devir))
	print(("%-13s : %s"):format(messages.package_info_arch,mimari))
	print(("%-13s : %s"):format(messages.package_info_pack_size,aboyut))
	print(("%-13s : %s"):format(messages.package_info_inst_size,kboyut))
	print(("%-13s : %s"):format(messages.package_info_status,durum))
	print("-----------------------------------------")
end

function islem.bilgi.handler(input)
	local blist={}
	local durum=""
	-- todo!!! farklı bilgi parametreleri olacak
	local function pk_analiz(_paket)
		local path = islem.talimat_bul.job(_paket)
		
		if islem.paket.kurulu_kontrol(_paket) then
			blist[_paket]={durum="kurulu",talimatdir=path}
		elseif path then
			blist[_paket]={durum="talimat",talimatdir=path}
		else
			messages.package_not_found:format(_paket):yaz(0)
		end
	end

	local function status_print(tdir)
		local _pk,_=tdir:match("([%a%d-_+]+)#+")
		if islem.paket.kurulu_kontrol(_pk) then 
			print(("%-25s : %s"):format(cmd.basename(tdir):run(),"+"))
		else
			print(("%-25s : %s"):format(cmd.basename(tdir):run(),"-")) 
		end
	end
	
	-- konsoldan girilen paket girdi analiz
	if input.paket then
		for _,pk in ipairs(input.paket) do pk_analiz(pk) end
	end
	
	-- bilgi test işlevi
	if input.test then
		for pk,info in pairs(blist) do print(pk,info.durum,info.talimatdir) end
	else
		-- test olmadığı durumdaki işleyiş
		for paket,info in pairs(blist) do
			if input.gerek == "d" or input.gerek == "c"  then
				islem.gerek.job(info.talimatdir,input.gerek)
				print("-------")
				for _,tdir in ipairs(islem.gerek.liste) do 
					status_print(tdir)
				end 
			elseif input.gerek == "td" or input.gerek == "tc" then
				islem.tgerek.job(paket,input.gerek:sub(2))	
			-- bu api erişimleri tablodan sağlanacak
			elseif input.kk then
				islem.api.kk.job(paket)
			elseif input.kdl then
				print(islem.paket.kurulu_icerik(paket))
			elseif input.pl then
				print(islem.paket.shlib(paket,"pl"))
			elseif input.lg then
				print(islem.paket.shlib(paket,"lg"))
			elseif input.pkd then
				print(islem.paket.kurulum_dogrula(paket))	
			else
				info.paket=paket
				islem.bilgi.job(info)
			end
		end
	end
end

-- -kk kurulu kontrol
islem.api.kk={
	usage="",
	comment="bir paketin kurulu olma durumunu verir.",
}

islem.api.kk.job=function (pk)
	--- todo!!!! değerlere çıktı verilecek.
	-- nil   : tanımsız
	-- true  : kurulu
	-- false : kurulu değil
	if islem.paket.kurulu_kontrol(pk) then
		messages.installed:yaz(1)
	else
		messages.not_installed:yaz(3)
	end
end

-- -pkd paket kurulum doğrula
islem.api.pkd={
	usage="",
	comment="",
}

-----
function islem.paket.shlib(paket,tip)
	-- kurulu olan bir paketin paket ve gerekli shliblerini gösterir.
	-- todo 2021-12 td ve kd farkı incelenecek
	assert(paket,"paket param is nil")
	local icerik=""
	local kd=""
	local td=""
	local fark=""
	local _talimatd=islem.talimat_bul.job(paket)
	if _talimatd then
		if tip== "lg" then
			td=_talimatd.."/"..islem.shlib.dosya
		elseif tip== "pl" then
			td=_talimatd.."/"..islem.paket.pktlib_dosya
		else
			("geçersiz shlib tipi:"..tip):yaz(0)
		end
		if stat(td) then
			icerik=get_content(td)
		end
	else
		(messages.talimat_not_found..paket):yaz(0)
	end
	-- paket kurulu ise onun da sh bilgisi incelenecek
	if islem.paket.kurulu_kontrol(paket) then
		
		if tip== "lg" then
			kd=kokdizin..islem.paket.vt..paket.."/"..islem.paket.metadir..islem.shlib.dosya
		elseif tip== "pl" then
			kd=kokdizin..islem.paket.vt..paket.."/"..islem.paket.metadir..islem.paket.pktlib_dosya
		else
			("geçersiz shlib tipi:"..tip):yaz(0)
		end
		-- kurulu lib
		print(get_content(kd))
	else
		-- talimat lib
		print(icerik)
	end
	
end

function islem.paket.pkvt_bilgi(paket)
	-- bir paket hakkında pkvt leri tarayarak bilgi toplar.
	local paketler={}
	local i=0
	-- isim,surum,devir,mimari,aboyut,kboyut,shasum içeriği olacak.
	local fields={"isim","surum","devir","mimari","aboyut","kboyut","shasum","depo"}
	local ret=""
	--local komut='busybox find %s -name "paket.vt#%s" -exec grep -i "^%s " {} \\; | sort -n'
	-- 2021-12 sort edilecek 
	--local komut='rg -IN "^%s " %s -g paket.vt#%s'
	local komut=cmd.grep("-IN","^"..paket.." ",kokdizin..islem.paket.cachedir)
	-- islem.paket.cachedir altında paketleri arayacak.
	-- {} /dev/null \; olursa eşleşen dosya ismi de gelir.
	-- en azından paket.vt#1 dosyası bulunmalıdır ki tarama yapılabilsin
	--if path_exists(islem.paket.cachedir.."/paket.vt#1") then

	for sira=1,#ayar.sunucu do
		if stat(kokdizin..islem.paket.cachedir.."/paket.vt#"..sira) then
			--ret=(komut:format(paket, kokdizin..islem.paket.cachedir,sira)):run()
			ret=(komut..(" -g paket.vt#%s"):format(sira)):run()
			for satir in ret:gmatch("[^\r\n]+") do
				local _paket={}
				for bilgi in satir:gmatch("%S+") do
					i = i + 1
					_paket[fields[i]]=bilgi
				end
				-- depo bilgisi conf.lua dan alınıp eklenecek.
				_paket.depo=ayar.sunucu[sira]
				table.insert(paketler,_paket)
				i=0
			end
		else
			(sira..". "..messages.paketvt_not_found):yaz(0)
		end
	end
	if #ayar.sunucu == 0 then
		messages.package_server_not_defined:yaz(3)
	end
	return paketler
end


function islem.paket.pkvt_bilgi_2(talimatdir)
	local pk,_=talimatdir:match("([%a%d-_+]+)#+")
	local i = 0
	-- bir paket hakkında pkvt leri tarayarak bilgi toplar.
	local paketler={}
	local i=0
	-- isim,surum,devir,mimari,aboyut,kboyut,shasum içeriği olacak.
	local fields={"isim","surum","devir","mimari","aboyut","kboyut","shasum","depo","cid"}
	local ret=""
	local komut=cmd.grep("-IN","^"..pk.." ",talimatdir)
	if stat(talimatdir.."/paket") then
	    ret=(komut.." -g paket"):run()
	    for satir in ret:gmatch("[^\r\n]+") do
	      local _paket={}
	      for bilgi in satir:gmatch("%S+") do
		i = i + 1
 		_paket[fields[i]]=bilgi
	      end
              table.insert(paketler,_paket)
	      i=0
	    end
	end
	return paketler
end


function islem.paket.kurulu_kontrol(paket)
	-- bir paketin kurulu olup olmadığını vt e bakarak kontrol eder
	-- /var/lib/mps/DB/paket_ismi dizin kontrol eder
	assert(paket,"islem.paket.kurulu_kontrol : paket is nil")
	if stat(kokdizin..islem.paket.vt..paket.."/"..islem.kur.kurulandos) then
		return true
	end
	return nil
end

function islem.paket.kurulu_icerik(paket)
	-- kurulu olan bir paketin kurulum içeriğini gösterir
	-- önce kontrol edilir
	assert(paket,"islem.paket.kurulu_kontrol : paket is nil")
	if islem.paket.kurulu_kontrol(paket) then
		local _kurulan=kokdizin..islem.paket.vt..paket.."/"..islem.kur.kurulandos
		assert(stat(_kurulan),"islem.paket.kurulu_icerik : kurulan file not found")
		local icerik=get_content(_kurulan)
		print(icerik)
		-- clear screen
		--io.write("\27[2J")
	else
		messages.package_not_installed:format(paket):yaz(0)
	end
end

function islem.paket.kurulum_dogrula(paket)
	-- kurulu olan bir paketin dosyaları incelenerek kurulum doğrulaması yapılır
	-- mevcutluk ve hash kontrolü + izinler ! todo!!!
	assert(paket,"islem.paket.kurulum_dogrula : paket is nil")
	if islem.paket.kurulu_kontrol(paket) then
		-- paket dizin kaydı
		local _file=kokdizin..islem.paket.vt..paket.."/kurulan"
		if stat(_file) then
			for line in (get_content(_file)):gmatch("[^\r\n]+") do 
				if not stat(kokdizin..line) then
					messages.file_not_found:format(line):yaz(1)
				end 
			end
		else	
			messages.file_not_found:format(_file):yaz(0)
		end
	else
		messages.package_not_installed:format(paket):yaz(0)
	end
end

function islem.paket.kurulum_bilgileri(paket)
	-- kurulu olan bir paketin üstbilgi dosyası incelenerek bilgiler döndürülür.
	assert(paket,"islem.paket.kurulum_bilgileri : paket is nil")
	local _pb={}
	local sahalar={"isim","surum","devir","tanim","url","paketci","grup","boyut","derzaman","thash","mimari"}
	local _file=kokdizin..islem.paket.vt..paket.."/"..islem.paket.metadir..islem.paket.ustbildos
	if stat(_file) then
		for line in (get_content(_file)):gmatch("[^\r\n]+") do 
			for _,saha in ipairs(sahalar) do
				val=line:match(saha.."=(.*)")
				if val then _pb[saha]=val end
			end
		end
	else	
		messages.file_not_found:format(_file):yaz(0)
	end
	return _pb
end

------------------------------

------------------Sorgu  İşlemleri-----------------------

islem.sorgu={retkey="sorgu:",}

function islem.sorgu.handler(input)
	-- todo!!! farklı sorgu parametreleri olacak
	-- sorgu test işlevi
	if input.test then
		print("sorgu işlevi testleri...")
	end
		
	-- kurulu paketlerin listesi
	if input.kpl then
		local pvt=kokdizin..islem.paket.vt
		local komut=cmd.pipe(cmd.grep("-IN --hidden -U --multiline-dotall  -e 'isim.*surum.*devir' -g .ustbilgi","",pvt),cmd.paste("^","- - -"))
		local cikti=komut:run()
		local isim,surum,devir="","",""
		for line in cikti:gmatch("[^\r\n]+") do 
			isim,surum,devir=line:match("isim=([%a%d-_+]+)^surum=([%d%a.]+)^devir=([%d]+)")
			print(("%-20s %-9s %-3s"):format(isim,surum,devir))
		end
	end
	
	-- depolardaki paketlerin listesi
	if input.dpl then
		local komut=cmd.pipe(cmd.cat(kokdizin..islem.paket.cachedir.."/paket.vt#*"),cmd.awk("","{print $1,$2,$3}"),"column -t")
		print(komut:run())
	end
	
	-- temel paketlerin listesi
	if input.tpl then
		print(cmd.pipe(cmd.ls("-d",talimatname.."/1/*#*"),xbasename,cmd.cut('#',1)):run())
	end
	
	-- arama girdisinin hangi pakette geçtiğini bulur
	if input.hp then
		local aranan=input.hp
		local pvt=kokdizin..islem.paket.vt
		local komut=cmd.grep("-iN",aranan,pvt).." -g kurulan"
		print(komut:run())
	end
	
	-- arama girdisinin altındaki talimatları listeler
	if input.gtl then
		local aranan=input.gtl
		local komut=cmd.pipe(cmd.grep("--sort path --files", "", talimatname).." -g talimat", cmd.grep("", "/"..aranan.."/", ""), xdirname, xbasename, cmd.cut('#',1))
		print(komut:run())
	end
end

------------------İndirme İşlemleri-----------------------
-- handler parametre analiz ve linki hazırlayacak
-- job direk linki hash kontrollü indirecek

islem.indir={
	retkey="indir",
	usage="mps indir paket_ismi",
	comment=messages.comment_mps_download
}

function islem.indir.handler(input)
	-- paket bilgileri yer alacak
	local inlist={}
	-- öntanımlı 1.depodan çekmektedir.
	local sira=1
	-- girdi olarak varsa depo sırası güncellenecek
	if input.sira then sira=tonumber(input.sira) end
	
	local function pk_analiz(pkt)
		local ret=islem.paket.pkvt_bilgi(pkt)
		if ret then
			-- indir işlemi paket bilgi tablosunu kullanacak.
			if ret[sira] then
				table.insert(inlist,ret[sira])
			else
				messages.package_not_found_inrepo:format(pkt):yaz(0)
			end
		else
			print(pak,"depolarda bulunamadı")
		end
	end
	
	-- konsoldan girilen paket girdi analiz
	if input.paket then
		for _,pk in ipairs(input.paket) do pk_analiz(pk) end
	end
	
	-- dosya parametresi içerik girdi analiz
	if input.dosya then
		if stat(input.dosya) then
			for pk in (get_content(input.dosya)):gmatch("[^\r\n]+") do 
				pk_analiz(pk)
			end
		else	
			messages.file_not_found:format(dosya):yaz(0)
		end
	end
	
	-- indirme test işlevi
	if input.test then
		for _,pk in ipairs(inlist) do print("s",pk) end
	else
		-- test yoksa indirme işlemi yapacak
		for _,pb in ipairs(inlist) do
			islem.indir.job(pb)
		end
	end	
end

function islem.indir.job(pb)
	-- girdi olarak paket bilgi tablosu alır.
	-- Link ve paket arşiv formatlarına ayrıştırır.
	assert(pb,"paket bilgi tablosu nil")
	-- indirilecek link ve kayıt yolu+dosya ismiyle
	function _indir(link,kayit)
		local body, code = http_request(link,"progress")
		code=tostring(code)
		if code=="can't connect" then
			messages.server_connection_refused:format(link):yaz(3)
		elseif code=="404" then
			messages.paketvt_not_found:yaz(3)
		elseif code == "200" then
			local f = assert(io.open(kayit, 'wb'))
			f:write(body)
			f:close();
			if stat(kayit) then
				(link):yaz(1);
			else
				messages.redownloading:format(kayit):yaz(2)
				_indir(link,kayit);
			end
		elseif not body then
			(link):yaz(3);
		else
			messages.unknown_error:format(link):yaz(0)
		end
	end

	-- arşiv formatında # , web için %23 olauyor.
	-- Bu nedenle global arşiv formatını kullanmıyoruz.
	local larsiv=("%s%%23%s-%s-%s.mps.lz"):format(pb.isim,pb.surum,pb.devir,pb.mimari)
	local arsiv=paf:format(pb.isim,pb.surum,pb.devir,pb.mimari)
	local indirilecek=true
	-- link oluşturulur
	if pb.depo:find("ipfs") then
	  larsiv=pb.cid
	end
	local link=plf:format(pb.depo,larsiv)
	local kayit=kokdizin..islem.paket.cachedir.."/"..arsiv
	-- print(link,"indirilecek")
	-- indirme işlemi; indirme yöneticisine link ve kayıt yeri belirtilir.
	if stat(kayit) then
		-- eğer paket önbellekte var ise hash kontrolü yapılıp
		-- hatalı ise silinip tekrar indirilir.
		if hash_check(kayit,pb.shasum) then
			indirilecek=false;
			messages.package_incache:format(pb.isim):yaz(2)
			-- paketin zaten indirilmiş olduğu-doğrulanması, dönüş kayit yol.
			return kayit
		else
			messages.package_shasum_error:format(pb.isim):yaz(3)
			messages.package_redownloading:format(pb.isim):yaz(2)
			cmd.remove(kayit):run()
		end
	end

	if indirilecek then
		--messages.package_downloading:format(pb.isim):yaz(1)
		(pb.isim.." indiriliyor"):yaz(1)
		_indir(link,kayit)
		-- shasum kontrol; indirilen dosya mevcut ve hash kontrolü yapılır.
		if stat(kayit) then
			if hash_check(kayit,pb.shasum) then
				messages.package_downloaded:format(pb.isim):yaz(1)
				-- paketin indirilmesi-doğrulanması, dönüş kayit yol.
				return kayit
			else
				messages.package_shasum_error:format(pb.isim):yaz(0)
			end
		else
			messages.package_download_error:format(pb.isim):yaz(0)
		end
	end
	-- diğer durumlar için nil değerin döndürülmesi
	return nil
end
------------------------------------------------------------

-- Koşuk işlemleri - kurkos,koskur,silkos, kossil

islem.kosuk={
	retkey="kosuk:",
	predos=".koskur",
	postdos=".kurkos",
	postrm=".silkos",
	prerm=".kossil",
}

-- koşuklar için çalıştırma işlevi
function islem.kosuk.kos(kosuk)
	if stat(kosuk) then
		cmd.chmodx(kosuk):run()
		if os.execute(kosuk) then
			return "OK"
		else
			return "FAIL"
		end
	else
		return "PASS"
	end
end

-- kurmadan önce çalıştırılacak kod
function islem.kosuk.koskur(tempdir)
	local log="kosuk.koskur:"
	if islem.kur.koskur then
		assert(stat(tempdir),"islem.kosuk.koskur : tempdir is nil")
		local kos=tempdir..islem.paket.metadir..islem.kosuk.predos
		log=log.."\t"..islem.kosuk.kos(kos)
	else
		log=log.."\tDISABLE"
	end
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")
end

-- kurmadan sonra çalıştırılacak kod
function islem.kosuk.kurkos(tempdir)
	local log="kosuk.kurkos:"
	if islem.kur.kurkos then
		assert(stat(tempdir),"islem.kosuk.kurkos : tempdir is nil")
		local kos=tempdir..islem.paket.metadir..islem.kosuk.postdos
		log=log.."\t"..islem.kosuk.kos(kos)
	else
		log=log.."\tDISABLE"
	end
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")
end

-- kurulumda dosya-dizin tetiklemeli otomatik çalıştırılacak kod
-- buna daha farklı yol bulunmalı - talimatta açıkça belirtilebilir.
-- 2021-12 todo!!!
function islem.kosuk.otokos_kur(tempdir)
	local log="kosuk.otokos:"
	if islem.kur.otokos then
		assert(stat(tempdir),"islem.kosuk.otokos : tempdir is nil")
		local curdir=getcwd()
		chdir(tempdir)
		kos=mps_path.."/conf/otokos.sh"
		cmd.chmodx(kos):run()
		os.execute(kos.." kur")
		log=log.."\tOK"
		chdir(curdir)
	else
		log=log.."\tDISABLE"
	end
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")
end

-- silmeden önce çalıştırılacak kod
function islem.kosuk.kossil(paket)
	assert(stat(kokdizin..islem.paket.vt..paket),"islem.kosuk.kossil : paketdir is nil")
	local kos=kokdizin..islem.paket.vt..paket.."/"..islem.paket.metadir..islem.kosuk.prerm
	local log="kosuk.kossil:"
	log=log.."\t"..islem.kosuk.kos(kos)
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
end

-- sildikten sonra çalıştırılacak kod
function islem.kosuk.silkos(paket)
	assert(stat(kokdizin..islem.paket.vt..paket),"islem.kosuk.silkos : paketdir is nil")
	local kos=kokdizin..islem.paket.vt..paket.."/"..islem.paket.metadir..islem.kosuk.postrm
	local log="kosuk.silkos:"
	log=log.."\t"..islem.kosuk.kos(kos)
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
end

------------------------------

-- Sil işlemleri

islem.sil={
	retkey="sil:",
	usage="mps sil paket_ismi",
	dlistfile="%stmp/%s.del.list",
	keeplist=".silme",
	logdir=islem.paket.logdir.."sil/",
	force_remove_dirs={"__pycache__"},
	logger=nil,
	silkos=true,
	kossil=true,
}

function islem.sil.handler(input)
	local remlist={}
	--for k,pk in pairs(input) do print(k,pk) end
	--print(input.paket)
	if input.silkos == "0" then islem.sil.silkos=false end
	if input.kossil == "0" then islem.sil.kossil=false end
	
	local function pk_analiz(_paket)
		local _durum=""
		-- paketin kurulu kontrolünün atlanması için
		if input.kksiz then
			_durum=true
		else
			_durum=islem.paket.kurulu_kontrol(_paket)
		end
		if _durum then
			if input.ona then
				table.insert(remlist,_paket)
			else
				if islem.diyalog.onay(messages.confirm_package_uninstallation:format(_paket)) then
					table.insert(remlist,_paket)
				end
			end
		else
			messages.package_not_installed:format(_paket):yaz(3)
		end
	end
	
	-- konsoldan girilen paket girdi analiz
	if input.paket then
		for _,pk in ipairs(input.paket) do pk_analiz(pk) end
	end
	
	-- dosya parametresi içerik girdi analiz
	if input.dosya then
		if stat(input.dosya) then
			for pk in (get_content(input.dosya)):gmatch("[^\r\n]+") do 
				pk_analiz(pk)
			end
		else	
			messages.file_not_found:format(dosya):yaz(0)
		end
	end
	
	-- silme test işlevi
	if input.test then
		for _,pk in ipairs(remlist) do print("s",pk) end
	else
		-- test yoksa bu işlem yapılacak
		for _,rpaket in ipairs(remlist) do
			-- todo!!! ters gereklerini kontrol et / silinecek pakete bağlı olan paketler
			if input.db then 
				islem.sil.only_vt(rpaket)
			else	
				islem.sil.job(rpaket)
			end
		end
	end	
	-- silmesi onaylanmış paket sayı bilgisi
	-- sistem güncellemede kullanılacak.
	return #remlist	
end

function islem.sil.job(paket)
	-- tek bir paketi siler
	assert(paket,"islem.sil.paket : paket is nil")
	-- sil adımları
	-- 0. logger set
	islem.sil.set_logger(paket)
	-- 1. silinecek dosya listesi hazırla
	islem.sil.prepare_list(paket)
	-- 2. silinecekleri filtrele(keeplist)
	islem.sil.filter_list(paket)
	-- 3. kos-sil betiğini kontrol et / çalıştır
	islem.kosuk.kossil(paket)
	-- 4. Dosyaları güvenli! sil ve logla
	islem.sil.uygula(paket)
	-- 5. sil-kos betiğini kontrol et / çalıştır
	islem.kosuk.silkos(paket)
	-- 6. paket veritabanı güncelle sil
	islem.sil.paket_vt(paket)
	-- silmeden sonra ld.so.cache güncellemesi için
	islem.kur.ld_update("sil");
	-- log dosyası kapatılır.
	islem.sil.logger:close();
	-- Silme işlemi sonuç kontrol
	islem.sil.bitis(paket)
end

function islem.sil.set_logger(paket)
	-- bu assert mps başına konulabilir
	assert(stat(kokdizin..islem.paket.logdir),"islem.sil.set_logger : islem.paket.logdir is not availables, needs mps --ilk")
	assert(stat(kokdizin..islem.sil.logdir),"islem.sil.set_logger : islem.sil.logdir is not availables, needs mps --ilk")
	local logfile=kokdizin..islem.sil.logdir..paket..".log"
	islem.sil.logger = assert(io.open(logfile, "w"),"islem.sil.set_logger logfile can not open")
	islem.sil.logger:write(paket.."\t"..os.date("%x %H:%M:%S").."\n");
	islem.sil.logger:write("--------------------------------------\n");
end

function islem.sil.bitis(paket)
	-- Silme adımlarının başarılı bir şekilde tamamlandığını log dosyası ile kontrol eder.
	local logfile=kokdizin..islem.sil.logdir..paket..".log"
	assert(stat(logfile),"islem.sil.bitis : logfile is not available")
	if not get_content(logfile):match("ERR@R") then
		messages.package_uninstalled:format(paket):yaz(1)
	else
		messages.package_uninstallation_failed:format(paket):yaz(0)
	end
end

function islem.sil.prepare_list(paket)
	local sildos=islem.sil.dlistfile:format(kokdizin,paket)
	local _kurulan=kokdizin..islem.paket.vt..paket.."/"..islem.kur.kurulandos
	-- todo!!! silinecek dosyaların başına kök diizn ekleyerek gerçek yollu silineceklerin oluşturulması
	--local komut='sed "s~^\'~%s~g"  %s | sed "s/\'//" > %s'

	-- silinecek dosyalardan ' karakterinin kaldirilmasi
	--local komut="busybox sed 's/'\\''//g' %s > %s"
	
	local komut="%s > %s"
	komut=komut:format(cmd.pipe(cmd.cat(_kurulan),cmd.sed("'s/'\\''//g'")),sildos)
	komut:run()
	assert(get_size(sildos) > 0,"islem.sil.prepare_list : del.list is empty");
	local log="prepare_list:\tOK"
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
end

function islem.sil.filter_list(paket)
	-- eğer paket dizin kaydında .silme isimli dosya varsa
	-- o dosya içindeki alt alta sıralı dosyalar silinecekler listesinden elenecektir.
	-- silinecekler başka dosya isimle içindekilerle karşılaştırılıp filtre edilenler silinir.
	local keeplistfile=kokdizin..islem.paket.vt..paket.."/"..islem.sil.keeplist
	local sildos=islem.sil.dlistfile:format(kokdizin,paket)
	local log=""
	if stat(keeplistfile) then
		--local komut_k='busybox sed "s~^~%s~g" %s > %s'
		local komut_k="%s > %s"
		komut_k:format(cmd.pipe(cmd.cat(keeplistfile),cmd.sed(("s~^~%s~g"):format(kokdizin))),sildos..".keep")		
		komut_k:run()
		cmd.move(sildos,sildos.."f"):run()
		local komut_f="%s > %s"
		komut_f:format(cmd.pipe(cmd.cat2(sildos..".f",keeplistfile),cmd.sortp(),cmd.uniq("-u")),sildos)			
		komut_f:run()
		log="filter_list:\tOK"
	else
		log="filter_list:\tPASS"
	end
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
end

function islem.sil.uygula(paket)
	local sildos=islem.sil.dlistfile:format(kokdizin,paket)
	local sil_content=get_content(sildos);

	-- Once tum paket *dosya*lari silinecek
  -- Ardindan klasorler bos mu diye kontrol edilecek
  -- Bos olan klasorler kaldirilacak
	local exist=true
	local delete=true
	local log=""
	local ret=nil
	
	function smart_delete(file_list)
		-- smart delete bir dosya+dizin listesi alir
		-- Ilk olarak tum dosyalari kaldirir ve dizinleri arar
		-- Ardindan bos olan dizinler kaldirilir
		-- Son olarak bos olmayan dizinleri return eder

		-- file_list bir string arrayi olmali

		to_remove={
			files={},
			dirs={}
		}

		for dos in file_list:gmatch("[^\r\n]+") do
			--file_attr = lfs.attributes(dos)
			if stat(dos) then
				--if  file_attr.mode == "file" then
				if  not isdir(dos) then
					table.insert(to_remove.files, dos)
				else
					_, count = dos:gsub('/', '/')
					table.insert(to_remove.dirs, {dos, count})
				end
			end
		end

		-- tabloyu dizin hiyerasisine gore sirala
		-- alttaki dizin tabloda uste gelir
		function compare(a,b)
			return a[2] > b[2]
		end
		table.sort(to_remove.dirs, compare)

		-- once tum dosyalari kaldir
		for _,v in pairs(to_remove.files) do
			local result, reason = os.remove(v)
      -- todo!!! dosya silinmemesine karsin error-check yap
			if result then
			else
			end
		end

		nonempty_dirs={}

		-- to_remove.dirs'i iterate et ve bos olan dizinleri kaldir
		-- todo !!! buranın yenilenmesi gerek lfs. linklerde sorunlu.?
		-- 2021-12 todo!!!
		for i=1, #to_remove.dirs do
			-- zorla silinecek dizin kontrolü
			-- __pycache__ gibi, temel dizin adı ile kontrol edilmektedir.
			if has_value(islem.sil.force_remove_dirs,cmd.basename(to_remove.dirs[i][1]):run()) then
				cmd.remove(to_remove.dirs[i][1]):run()
			else
				--status, message, code = lfs.rmdir(to_remove.dirs[i][1])
				status, code = rmdir(to_remove.dirs[i][1])
			
				if status == nil then
					if code == 39 then						
						-- Dizin bos degil, silme!, nonempty_dirs'e ekle
						table.insert(nonempty_dirs, to_remove.dirs[i])
					elseif code == 20 then
						-- bir dizinin linki durumundadır
						-- todo!!! link ise zorla silinecektir. farklı durumlar gözlemlenecek.
						cmd.remove(to_remove.dirs[i][1]):run()
					else
						-- Hata yakala ve yazdir
						hata_msg="Klasör silinemedi!".."\n"..message..
						hata_msg:yaz(0)
					end
				end
			end
		end

		return nonempty_dirs
	end

	-- sildos dosyasindaki entryleri smart_delete function'i ile sil
	protected_dirs = smart_delete(sil_content)

	-- Kullaniciya silinmeyen klasorleri goster
	-- todo!!! bu ozelligi tamamla - kullanicidan input alip sil

	if #protected_dirs > 0  then
		log="sil.korunan:  \tOK";
		sildos_by_user=islem.sil.dlistfile:format(kokdizin, paket)..".kor"
		messages.confirm_dir_removing_msg:format(sildos_by_user):yaz(3)
		messages.confirm_dir_removing_info:format(sildos_by_user):yaz(3)
		sildos_file = io.open(sildos_by_user, "w")
		local ne_dir=""
		for i=1, #protected_dirs do
			-- kullanıcı girdilerine sahip dizinler
			ne_dir = protected_dirs[i][1]
			for fl in (cmd.grep("--files","",ne_dir):run()):gmatch("[^\r\n]+") do 
				print(fl)
				sildos_file:write(fl.."\n")
			end
		end
		sildos_file:close()
		islem.debug.yaz(log);
		islem.sil.logger:write(log.."\n")
	end
	----------
	if exist and delete then
		log="sil.uygula:  \tOK";
		islem.debug.yaz(log);
		islem.sil.logger:write(log.."\n")
	else
		log="sil.uygula:\tERR@R";
		log:yaz(3);
		islem.sil.logger:write(log.."\n")
	end

end

function islem.sil.paket_vt(paket)
	local dizin=kokdizin..islem.paket.vt..paket
	assert(stat(dizin),"islem.sil.paket_vt : dizin is not available")
	local log=""
	-- link dizinin sislinmesi
	cmd.remove(dizin):run()
	cmd.remove(dizin.."#*"):run()
	if not stat(dizin) then
		log="sil.paket_vt:\tOK";
		islem.debug.yaz(log);
		islem.sil.logger:write(log.."\n")
	else
		log="sil.paket_vt:\tERR@R";
		log:yaz(3);
		islem.sil.logger:write(log.."\n")
	end
end

function islem.sil.only_vt(paket)
	islem.sil.set_logger(paket)
	islem.sil.paket_vt(paket)
	islem.sil.logger:close()
	islem.sil.bitis(paket)
end

------------------------------

-- Kur işlemleri

islem.kur={
	retkey="kur:",
	kurulandos="kurulan",
	dizinler={"boot","etc","usr","opt","var","tools"}, -- paket içi desteklenen dizinler
	usage="mps kur paket_ismi | paket_yolu",
	logdir=islem.paket.logdir.."kur/",
	logger=nil,
	kurkos=true,
	koskur=true,
	otokos=true,
	zorla=false,
	comment=messages.comment_mps_install,
}

function islem.kur.agdan(paket)
	assert(paket,"islem.kur.agdan : paket is nil")
	-- 1.çalışma gerekleri tespit edilecek tablo=gerek paket c
	-- islem gerek listesi global olduğu için sıfırlanması gerekir.
	islem.gerek.liste={}
	islem.gerek.list={}
	if type(paket) == "table" then
		for _,p in ipairs(paket) do
			islem.gerek.job(p,"c")
		end
	else
		islem.gerek.job(paket,"c")
	end	
	--print(paket,#islem.gerek.liste)
	-- 2.paketvt ler den döngüde paket#surum-devir
	local ret, pk=""
	local kurliste={}
	local pkpath=nil
	-- 3. gereklerin sıralı indirme
	
	function controller(tsd)
		-- gerekli paket kurulu kontrolü yapılıp indirilir
		local pk,_=tsd:match("([%a%d-_+]+)#+")
		-- paket kurulu ise atlanacak
		if islem.paket.kurulu_kontrol(pk) then
			(messages.package_already_installed..":"..pk):yaz(2);
		else
			ret=islem.paket.pkvt_bilgi(pk)[1]
			-- paket paket veritabanında bulunamaz ise, veritabanı güncellenmelidir.
			if ret == nil then 
			  -- talimat dizininde yer alan paket bilgisine bakılır.
			  ret=islem.paket.pkvt_bilgi_2(tsd)[1]
			  -- print("t_paket:",ret.depo,ret.cid)
			end
			if ret == nil then messages.package_not_found_inpkvt:format(pk):yaz(0) end
			-- indirme işlemi
			-- kurliste ye inen/indirilmiş paketin yolunun kaydı
			-- ...
			pkpath=islem.indir.job(ret)
			if pkpath == nil then
				messages.package_dependency_dl_error:format(pk):yaz(3)
			else
				table.insert(kurliste,pkpath)
			end
		end
	end
	
	-- controller için görev tablosu
	local threads = {}
	
    function co_adder (tsd)
        -- create coroutine
        local co = coroutine.create(
            function ()
                controller(tsd)
            end)
        -- görev tablosuna işin(thread) eklenmesi
        table.insert(threads, co)
    end
	
	for _,tsd in ipairs(islem.gerek.liste) do
		-- 3.1 indirilecek size bilgi - kurulacak bilgi verilip onay ile
		-- eski kod için controller i aç dispatcher i kapat. 
		--controller(tsd)
		co_adder(tsd)
	end
	
	function dispatcher()
		while true do
			local n = #threads
			if n == 0 then break end -- no more threads to run
			for i=1,n do
				local status, res = coroutine.resume(threads[i])
				if not res then -- thread finished its task?
					table.remove(threads, i)
					break
				end
			end
		end
	end
	-- multithread kontrol ve indirme işlemi
	dispatcher()
	
	-- 4.gerekler kurulacak (yerelden kur ile cachedir den)
	for _,pkyol in ipairs(kurliste) do
		-- 4.1 indirilecek size bilgi - kurulacak bilgi verilip onay ile
		islem.kur.yerelden(pkyol)
	end
end

function islem.kur.yerelden(paket)
	--print (paket) -- belki bu mps.log a atılabilir/nereden talimatlandığına dair
	-- yerelden gelen paketin mevcut kontrolü
	-- gönderen işlevler yapamazsa
	if not paket then
		messages.package_not_found:format(paket):yaz(0)
	end
	assert(paket ~= "","islem.kur.yerelden : paket is empty string")
	-- print (paket,"yerelden")
	-- adımlar: loglanacak, her işlem adımı log dosyasına atacak
	-- önemli not: pcall ile işlemler uygulanacak, eğer break olursa sistem kaynaklı (ctrl+c vs)
	-- işlem adımı ve onu çağıran süreç job dosyası state kayıt edilecek.
	-- 0.  paket arşivi kontrol edilir
	local isim,surum,devir=islem.arsiv.kontrol(paket)
	local isd=pgf:format(isim,surum,devir)
	-- 1. logger set
	islem.kur.set_logger(isim)
	-- 2.  paket kurulu kontrol yapılır
	islem.kur.kurulu_kontrol(isim)
	-- 3.  /tmp altında geçici bir dizine çıkarılır
	local tempdir=islem.arsiv.cikar(paket)
	-- 4.  libgerekler kontrol edilir- ldconfig sor
	islem.shlib.kontrol(tempdir) --/ kontrol altına eksik shlibleri içeren paketler kurulabilir.
	-- 5.  hedef kurulum dizininde çakışan/var olan dosya kontrolü - kurulacak ve çakışan liste döndürür.
	local klist,clist=islem.kur.dosya_kontrol(tempdir)
	-- 6.  koşkur varsa çalıştırılır 2.madde?
	islem.kosuk.koskur(tempdir)
	-- 7.  kopyalanan dosyalar VT e yazılır, var/lib/mps/DB altına paketismi
	-- tempdir altında kurulan dosyası, .icbilgi, .ustbilgi, kosuklar, libgerekler, pktlibler
	islem.kur.vt_kayit(tempdir,klist,isd)
	-- 8.  geçici dizinden hedef dizin altına kopyalanır-cakışan liste gönderilir onlar kopyalanmaz.
	islem.kur.kopyala(tempdir,clist)
	-- 9.  mtree ile karşılaştırma doğrulanır
	-- 10.  ldconfig güncellemesi
	islem.kur.ld_update_handler(tempdir)
	-- 11.  kurkos çalıştırılır
	islem.kosuk.kurkos(tempdir)
	-- 12.  otokos çalıştırılır
	islem.kosuk.otokos_kur(tempdir)
	-- 13. temizlik, başarı mesaj...
	islem.kur.clean_tempdir(tempdir)
	-- 14. log dosyası kapatılır.
	islem.kur.logger:close();
	-- 15. Paket kurulum sonucu
	islem.kur.bitis(isim)
end

function islem.kur.clean_tempdir(tempdir)
	-- kurulum içeriğinin geçici çıkarıldığı tempdir silinir.
	cmd.remove(tempdir):run()
end

function islem.kur.bitis(paket)
	-- Kurulum adımlarının başarılı bir şekilde tamamlandığını log dosyası ile kontrol eder.
	local logfile=kokdizin..islem.kur.logdir..paket..".log"
	assert(stat(logfile),"islem.kur.bitis : logfile is not available")
	if not get_content(logfile):match("ERR@R") then
		messages.package_installed:format(paket):yaz(1)
	else
		messages.package_installation_failed:format(paket):yaz(0)
	end
end

function islem.kur.set_logger(paket)
	-- bu assert mps başına konulabilir
	assert(stat(kokdizin..islem.paket.logdir),"islem.kur.set_logger : islem.paket.logdir is not available, needs mps --ilk")
	assert(stat(kokdizin..islem.kur.logdir),"islem.kur.set_logger : islem.kur.logdir is not availables, needs mps --ilk")
	local logfile=kokdizin..islem.kur.logdir..paket..".log"
	--print("-",logfile)
	islem.kur.logger = assert(io.open(logfile, "w"),"islem.kur.set_logger logfile can not open")
	islem.kur.logger:write(paket.."\t"..os.date("%x %H:%M:%S").."\n");
	islem.kur.logger:write("--------------------------------------\n");
end

function islem.kur.ld_update_handler(tempdir)
	local log=""
	if stat(tempdir..islem.paket.metadir..islem.paket.pktlib_dosya)
	or stat(tempdir..islem.paket.metadir..islem.shlib.dosya) then
		-- libgerek?(kurulu ise cache edilmiş olmalı), shlib varsa ldconfig edilecek.
		islem.kur.ld_update()
		log="ld_up_handler:\tOK";
		islem.kur.logger:write(log.."\n")
	else
		messages.ld_update_pass:yaz()
		log="ld_up_handler:\tPASS";
		islem.kur.logger:write(log.."\n")
	end
end

-- kura mahsus olmasın todo!!!
function islem.kur.ld_update(oper)
	-- hedef kök dizinde ldconfig varsa güncelleme olur.
	local log=""
	if stat(kokdizin.."usr/bin/ldconfig")
	or stat(kokdizin.."sbin/ldconfig") then
		--print("ldconfig update edilecek")
		local cachedos="etc/ld.so.cache"
		cmd.remove(kokdizin..cachedos):run()
		local komut2=("ldconfig -r %s"):format(kokdizin)
		--print(komut2)
		komut2:run()
	else
		(messages.ld_update_pass..kokdizin):yaz()
		log="ld_update:\tPASS";
		if oper then
			islem[oper].logger:write(log.."\n")
		else
			islem.kur.logger:write(log.."\n")
		end
	end
end

function islem.kur.kopyala(dir,nclist)
	-- geçici çıkarma dizininden sisteme kopyala işlemi
	-- geçerli dizinler kontrol edilerek kopyalama yapılır
	-- tempdir altındaki dizinleri islem.kur.dizinler ile karşılaştır.
	-- kopyalanmayacaklar silinir.
	if next(nclist) then
		for _,f in ipairs(nclist) do
			cmd.remove(dir.."/"..f):run()
		end
	end
	-- kalan dizin yapısı ile hedef altına kopyalama yapılır.
	for _,d in ipairs(islem.kur.dizinler) do
		if stat(dir.."/"..d) then
			cmd.copy(dir.."/"..d, kokdizin.."/"):run()
		end
	end
	log="kur.kopyala:\tOK";
	--log="kur.kopyala:\tFAIL";
	islem.debug.yaz(log)
	islem.kur.logger:write(log.."\n")
end

function islem.kur.vt_kayit(dir,list,isd)
	-- sisteme kopyalanan paketin paket veritabanı kaydının yapılması
	-- ve kurulum logunun oluşturulması (adımlar loglanacak)
	-- dir abc#1.2-1.dir
	local pack_name=isd:split("#")[1]
	local link_name=isd
	mkdir(kokdizin..islem.paket.vt.."/"..pack_name)
	cmd.copy(dir.."/.icbilgi", kokdizin..islem.paket.vt.."/"..pack_name.."/"):run()
	cmd.copy(dir.."/.meta", kokdizin..islem.paket.vt.."/"..pack_name.."/"):run()
	local file=io.open(kokdizin..islem.paket.vt.."/"..pack_name.."/kurulan","w")
	for _,f in ipairs(list) do
		file:write("/"..f.."\n")
	end
	file:close()
	-- mps hızlı bulma için vt linklemesi
	link(kokdizin..islem.paket.vt.."/"..pack_name,kokdizin..islem.paket.vt.."/"..link_name)
	log="kur.vt_kayit:\tOK";
	islem.debug.yaz(log)
	islem.kur.logger:write(log.."\n")
	-- vt_kayıt test edilecek!!!
end

function islem.icbilgi.dosyalar(dir)
	assert(stat(dir.."/.icbilgi"),dir.."/.icbilgi".." is not exist")
	local cnt=cmd.gzipd(dir.."/.icbilgi"):run()
	assert(cnt,"content is empty")
	install_list={}
	overwrite_list={}
	for _,line in ipairs(cnt:split("\n")) do
		if line:sub(1,2) == "./" then
			ifile=line:split(" ")[1]:sub(3,-1)
			is_dir=line:match("type=dir")
			--dizin ve dosya yok ise kurulan listeye ekle
			-- dosya ve var ise çakışan listeye ekle
			if not stat(kokdizin..ifile) then
				table.insert(install_list,ifile)
			elseif not is_dir and stat(kokdizin..ifile) then
				table.insert(overwrite_list,ifile)
			end
		end
	end
	return install_list, overwrite_list
end

function islem.kur.dosya_kontrol(tempdir)
	-- sisteme kopyalanacak paket içeriğinin sistemde çakışan karşılık kontrolü
	-- çakışanlar için strateji belirlenmeli: üzerine yaz, koru vs
	-- clist conflict files
	local clist_sil = true
	local list,clist=islem.icbilgi.dosyalar(tempdir)
	-- handling already exist files
	if islem.kur.zorla == false then
		-- list kurulacaklar
		if #clist > 0 then
			for _,cfile in ipairs(clist) do
				(messages.file_already_exists:format(kokdizin..cfile)):yaz(3)
			end
			if islem.diyalog.onay(messages.confirm_files_removing) == false then
				clist_sil = false
			end
		end
		log="çakışan_dosya:\tOK";
	else
		log="dosya_kontrol:\tOK";		
	end
	if clist_sil then
		for _,cfile in ipairs(clist) do
			table.insert(list,cfile)
			if cfile == "usr/bin/bash" or cfile == "usr/bin/sh" then  
				cmd.copy(tempdir..cfile, kokdizin..cfile):run()
			else
				cmd.remove(kokdizin..cfile):run()
			end
		end
		clist={}
	end
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")
	return list,clist
end

function islem.kur.kurulu_kontrol(paket)
	-- sistemde kurulu paket kontrolü
	-- burada kurulu pakete uygulanacak seçenek sorulur
	-- sil/silme
	assert(paket,"islem.kur.kurulu_kontrol : paket is nil")
	local log=""
	if islem.paket.kurulu_kontrol(paket) then
		log=messages.package_already_installed;
		messages.package_already_installed:yaz(0);
	else
		log="kurulu_kontrol:\tOK";
	end
	islem.debug.yaz(log)
	islem.kur.logger:write(log.."\n")
end

function islem.kur.job(kur)
	-- işlemlerin logu hazırlanacak.
	for tip,paketler in pairs(kur) do
		if kur[tip] then
			--tek tek paketleri işliyoruz
			if tip == "yerelden" then
				for _,paket in ipairs(paketler) do
					islem.kur.yerelden(paket)
				end
			elseif tip == "agdan" then
				islem.kur.agdan(paketler)
			else
				("bilinmeyen kurulum tipi"):yaz(0)
			end
		end
	end
end

function islem.kur.handler(input)
	-- işlem isminden sonra en az bir parametre olmalıdır.
	if input.kurkos == "0" then islem.kur.kurkos=false end
	if input.koskur == "0" then islem.kur.koskur=false end
	if input.otokos == "0" then islem.kur.otokos=false end
	if input.zorla 	== true then islem.kur.zorla=true  end
	
	local jobs={
		agdan={},
		yerelden={}
	}
	
	-- paketin yerel/ağ kaynak tespiti ve ilgili listeye eklenmesi
	function pk_analiz(pkt)
		local _paket=""
		if pkt:match("mps.lz") then 
			-- yerelden kurulacak listeye eklenir
			--print("yerelden kurulacak",pkt)
			table.insert(jobs.yerelden,cmd.readlink(pkt):run())
			_paket,_,_,_=pkt:match(paket_arsiv_pattern)
		else
			local _talimatd=islem.talimat_bul.job(pkt)
			if _talimatd then
				-- ağdan kurulacak listeye eklenir
				table.insert(jobs.agdan,_talimatd)
			else
				(messages.talimat_not_found..pkt):yaz(0)
			end
			_paket=pkt
		end
		-- tekrar parametresi verildiyse paketi silecek.
		if input.tekrar == true then
			islem.sil.handler({paket={_paket}})
		end
	end
	
	-- konsoldan girilen paket girdi analiz
	if input.paket then
		for _,pk in ipairs(input.paket) do pk_analiz(pk) end
	end
	
	-- dosya parametresi içerik girdi analiz
	if input.dosya then
		if stat(input.dosya) then
			for pk in (get_content(input.dosya)):gmatch("[^\r\n]+") do 
				pk_analiz(pk)
			end
		else	
			messages.file_not_found:format(dosya):yaz(0)
		end
	end
	
	-- handler işlevinin test işlemi
	if input.test then
		for _,v in ipairs(jobs.agdan) do print("a",v) end
		for _,v in ipairs(jobs.yerelden) do print("y",v) end
	else
		-- test yoksa bu işem yapılacak
		islem.kur.job(jobs);
	end			
	-- todo!!! işlemlerin logu okunacak
	-- ("işlemlerin logu okunacak"):yaz(2)
end
--------------------------------------------

--------Güncelleme İşlemleri-------------------

islem.guncelle={
	retkey="guncelle:",
	comment=messages.usage_updating_repos,
	usage="mps guncelle",
	betikdepo={isim="betikdepo",tnm="Betik",path=milispath},
	talimatdepo={isim="talimatdepo",tnm="Git",path=talimatname},
	paketlist={},
}
-- işlevler

function islem.guncelle.handler(input)
	local sira=tonumber(input.sira)
	-- mps güncelleme
	if input.mps then 
		islem.guncelle.mps() 
	end
	-- talimat depolarının güncelleme
	if input.git then 
		islem.guncelle.gitdepo(sira,islem.guncelle.talimatdepo) 
	end
	-- betik depolarının güncelleme
	if input.betik then
		islem.guncelle.gitdepo(sira,islem.guncelle.betikdepo)
	end
	-- paketvt depoları güncelleme
	if input.depo then 
		islem.guncelle.paketvt(sira)
	end
	-- sistem güncelleme
	if input.sistem then 
		islem.guncelle.sistem(input)
	end
	-- paket güncelleme
	if input.paket then 
		islem.guncelle.paket(input)
	end
	
	if not input.mps    and not input.git   and 
	   not input.betik  and not input.depo  and
	   not input.sistem and not input.paket then
		islem.guncelle.mps() 
		islem.guncelle.gitdepo(sira,islem.guncelle.talimatdepo)
		islem.guncelle.gitdepo(sira,islem.guncelle.betikdepo)
		islem.guncelle.paketvt(sira)
	end
end

function islem.guncelle.hesapla()
	
	local k_pak={}
	-- kpl işlevi
	local pvt=kokdizin..islem.paket.vt
	local komut=cmd.pipe(cmd.grep("-IN --hidden -U --multiline-dotall -e 'isim.*surum.*devir' -g .ustbilgi","",pvt),cmd.paste("^","- - -"))
	local cikti=komut:run()
	local paket,surum,devir="","",""
	local sd,pb,psd="",""
	for line in cikti:gmatch("[^\r\n]+") do 
		paket,surum,devir=line:match("isim=([%a%d-_+]+)^surum=([%d%a.]+)^devir=([%d]+)")
		sd=surum.."-"..devir
		pb=islem.paket.pkvt_bilgi(paket)[1]
		if pb == nil then psd=nil
		else psd=pb.surum.."-"..pb.devir end
		if psd ~= sd then
			islem.guncelle.paketlist[paket]={mevcut=sd,guncel=pb}
		end
	end 
end

function islem.guncelle.sistem(input)
	-- ilk önce talimatname ve paket depo eşitliğine bakılacak
	-- talimat ile paket sürümleri aynı olmak zorundadır yoksa derleyerek üretim gerekir.
	-- bu durum garantilendikten sonra ikili depodan güncelleme tespiti yapılıp sistem güncellenebilir.
	local esgeclist=input.esgec
	islem.guncelle.hesapla()
	local dppk=""
	for _paket,bilgi in pairs(islem.guncelle.paketlist) do
		if bilgi.guncel == nil then dppk="depoda olmayan paket"
		else dppk=bilgi.guncel.surum.."-"..bilgi.guncel.devir end
		if has_value(esgeclist,_paket) == true then
			print(_paket,"güncellemesi es geçildi.")
		else
			-- güncelleme işlemi - durum sorgulanacaksa işlem yaptırılmaz.
			if input.durum == true then
				-- güncelleme bilgisi
				print(string.format("%-15s %-10s -> %s",_paket,bilgi["mevcut"],dppk))
			else	
				islem.guncelle.paket({paket={_paket},ona=input.ona})
			end
		end
	end
	-- not islem.guncelle.paketlist key-value şeklinde # ile length alınamaz
end

function islem.guncelle.paket(input)
	-- 1 güncellenecek paket listesi için güncelleme hesaplanacak
	-- 2 guncellenecek paket listesinde yer alıyor mu 
	-- 3 paket depodan güncel paketi indir, doğrula
	-- 4 eski paketi kaldır. (geri kurtarma için eski paket depo?)
	-- 5 paketdepo inen yeni paketi kur.  
	-- -S ile guncellemeler hesaplanmış olabilir değilse hesaplanacak
	local paketgirdi=input.paket
	if next(islem.guncelle.paketlist) == nil then
		islem.guncelle.hesapla()
	end
	local pb,par,pyol=""
	-- silme onay değişkeni
	local s_onay=0
	-- döngü halinde paket listesindeki paketler güncellenecek.
	for _,paket in ipairs(paketgirdi) do
		if islem.guncelle.paketlist[paket] == nil then
			print(paket,"için güncelleme mevcut değil!")
		else
			pb=islem.guncelle.paketlist[paket]
			if pb.guncel == nil then
				print(paket,pb.mevcut,"depoda olmayan paket")
			else
				print(paket,pb.mevcut,pb.guncel.surum.."-"..pb.guncel.devir)
				islem.indir.handler({paket={paket}})
				par=paf:format(paket,pb.guncel.surum,pb.guncel.devir,pb.guncel.mimari)
				pyol=kokdizin..islem.paket.cachedir.."/"..par
				if stat(pyol) then
					s_onay=islem.sil.handler({paket={paket},ona=input.ona})
					if s_onay == 1 and islem.paket.kurulu_kontrol(paket) ~= true then 
						--islem.kur.yerelden(pyol)
						-- gerekler tekrar hesaplanacak
						islem.kur.agdan(islem.talimat_bul.job(paket))
					end
				else
					print(pyol,"güncellenecek paket yolu bulunamadı")
				end
			end
		end
		s_onay=0
	end
	--print("paket güncellemesi deneme kullanımındadır!")
end

function islem.guncelle.mps()
	-- todo!!! mps commit hash tutulacak oradan commit değer değişimi gösterilecek
	-- değişim yoksa güncelleme yok
	assert(stat(mps_path),"mps_path not exist")
	assert(stat(mps_path.."/.git"),"invalid git directory");
	("MPS güncelleniyor:"):yaz(2);
	("------------------------------------"):yaz(2);
	local komut="cd %s && git reset --hard HEAD && git pull --rebase; chmod +x bin/mps*"
	local ret=komut:format(mps_path):run();
	("------------------------------------"):yaz(2);
end

function islem.guncelle.paketvt(sira)
	-- todo!!! eskiden inen paketvt#x ler old a taşınacak
	-- başarılı indirmeler olunca silinecek şekilde ayarlanacak
	-- şu an bağlantı yoksa mevcutu da silimiş oluyor- bağlantı olmadan
	-- paket te inemez olarak kabul edildi.
	-- todo!!! bir önceki sürüm paketler için depo tahsisi ve güncellemelerde geri kurtarma deposu olarak kullanılması?
	local onbellek_depo=kokdizin..islem.paket.cachedir.."/"
	("Paket veritaban(lar)ı güncelleniyor:"):yaz(2);
	("------------------------------------"):yaz(2);
	-- paket önbellek depo yoksa oluşturulur.
	if not stat(kokdizin..islem.paket.cachedir) then
		cmd.mkdir(onbellek_depo):run()
	end
	-- Eski kalıntı paket.vt# dosyaları temizlenmesi
	cmd.remove(onbellek_depo.."paket.vt#*"):run()
	
	sira=tonumber(sira)
	local pkvt="paket.vt"
	-- işlev içinde işlev paket.vt i indirmek için
	-- paket.vt.gz gibi sıkıştırılmış gerçekleme yapılacak. todo!!!
	function _indir(sunucu,sira)
		-- io.write(sunucu.."/"..pkvt.."\t")
		local link=sunucu.."/"..pkvt
		local body, code = http_request(link)
		code=tostring(code)
		if code=="can't connect" then
			messages.server_connection_refused:format(sunucu):yaz(3)
		elseif code=="404" then
			messages.paketvt_not_found:yaz(3)
		elseif code == "200" then
			local kayit=onbellek_depo..pkvt.."#"..sira
			local f = assert(io.open(kayit, 'wb'))
			f:write(body)
			f:close();

			if stat(kayit) then
				(link):yaz(1);
			else
				messages.redownloading:format(kayit):yaz(2)
				_indir(sunucu,sira);
			end
		elseif not body then
			(link):yaz(3);
		else
			messages.unknown_error:format(link):yaz(0)
		end
	end

	-- eğer sadece bir paket sunucu güncellenmek istenirse
	if sira > 0 then
		-- sıra aşımlı paket vt güncellenmek istenirse
		if #ayar.sunucu < sira then
			messages.package_db_out_of_order:yaz(0)
		end
		if ayar.sunucu[sira]  then
			_indir(ayar.sunucu[sira],sira)
		end
	-- çoklu sunucu güncelleme - sıra 0 ve 0dan küçük ise
	else
		for _sira,sunucu in ipairs(ayar.sunucu) do
			_indir(sunucu,_sira)
		end
	end
	("------------------------------------"):yaz(2);
end

function islem.guncelle.gitdepo(sira,depo)
	-- tip=betikdepo, gitdepo
	-- depo={isim="betikdepo",tnm="Betik",path=milispath}
	-- depo={isim="gitdepo",tnm="Git",path=talimatname}
	-- bin, ayarlar lı betikdepo güncelleme yapılacak todo!!!
	assert(depo,"depo is nil!!!");
	(depo.tnm.." depoları güncelleniyor:"):yaz(2);
	("------------------------------------"):yaz(2);
	-- iç işlevler
	function do_clone(repo,path)
		local komut="git clone --depth 1 %s %s"
		local ret=komut:format(repo,path):run()
	end

	function do_pull(path)
		assert(stat(path.."/.git"),"invalid git directory")
		local komut="cd %s && git pull --ff-only"
		local ret=komut:format(path):run()
	end

	function esitle(repoyol,altdizin,hedef)
		-- todo!!! eşitlenecek dizinden sadece talimat içeren
		-- dizinleri alarak eşitleme yap veya sonda silme
		local komut="%s -rf %s/%s/* %s/"
		if stat(repoyol.."/"..altdizin) then
			cmd.mkdir(hedef):run()
			cmd.copy(repoyol.."/"..altdizin.."/*" ,hedef.."/"):run()
		else
			messages.git_repo_subdir_not_found:yaz(0)
		end
	end

	function yedekle(dizin)
		local komut="mv %s %s.ydk"
		assert(stat(dizin),dizin.." dizini yok!")
		komut:format(dizin,dizin):run()
		-- dizin yedeklenerek yeni boş oluşturulur.
		assert(mkdir(dizin),dizin.." oluşturulamadı.")
	end
	
	-- yedeklenen dizin güncellenemediğinden geri yedeklenir.
	function geri_yedekle(dizin)
		local komut="mv %s.ydk %s"
		assert(stat(dizin..".ydk"),dizin..".ydk dizini yok!")
		komut:format(dizin,dizin):run()
	end

	-- yedeklenen dizinin silinmesi
	function yedek_sil(dizin)
		assert(stat(dizin..".ydk"),dizin..".ydk dizini yok!")
		cmd.remove(dizin..".ydk"):run()
	end

	local _repo=""
	local _repoyol=""
	local duzey=""
	local tmp=("mktemp"):run()
	
	-- git repo mevcut kontrol komut
	local git_kont="git ls-remote -q %s > %s  2>&1;cat %s | head -n1 | awk '{print $1}'"
	-- !!! burası farklı ayar.betikdepo
	for bdepo,repolar in pairs(ayar[depo.isim]) do
		-- !!! burası farklı
		duzey=depo.path.."/"..bdepo
		-- her talimat-betik düzeyinde yedekleme-eşitleme-eskiyi silme yapılacak
		if stat(duzey) then
			yedekle(duzey)
		end
		for repo,dizin in pairs(repolar) do
			-- git repo mevcut kontrolü
			local ret=git_kont:format(repo,tmp,tmp):run()
			--io.write(bdepo," ",repo)
			print(("%-10s : %s"):format(bdepo,repo))
			if ret:match("fatal") then
				("\t-"):yaz(1)
			else
				-- Git işlemleri
				-- repo netde mevcut ise, yerelde yoksa clone varsa pull yapılacak.
				_repo=repo:gsub("https://", "")
				_repo=_repo:gsub("http://", "")
				_repo=_repo:gsub("/", ".")
				--print("\t",_repo)
				_repoyol=kokdizin..ayar.repo_dizin.."/".._repo
				if stat(_repoyol) then
					do_pull(_repoyol)
				else
					do_clone(repo, _repoyol)
				end
				-- Eşitleme işlemleri
				esitle(_repoyol,dizin,duzey)
			end
		end
		-- sıra-talimat düzeyi işlemler bittikten sonra .ydk düzey silinir.
		if stat(duzey..".ydk") then
			if rmdir(duzey) == true then
				geri_yedekle(duzey)
			else
				yedek_sil(duzey)
			end
		end
	end
	cmd.remove(tmp):run();
	("------------------------------------"):yaz(2);
end


-- Mps İşlemleri ----------------------------

-- -ayar öntanımlı ayarlar yükler/kopyalar

-- todo!!! mps kos altına alınacak
islem.ayarla={
	retkey="ayarla:",
	comment=messages.usage_configure,
	usage="mps ayarla",
}

function islem.ayarla.handler()
	-- mps için conf.lua yükleme komutu
	cmd.copy(mps_path.."/conf/conf.lua.sablon",mps_path.."/conf/conf.lua"):run()
end


------------------------------------------------------------

-----------------------------------------

-- Debug işlemleri

islem.debug={
	retkey="debug",
}

function islem.debug.yaz(log)
	if args.debug then
		if log then
			log:yaz()
		else
			messages.empty_log:yaz(0)
		end
	end
end
-----------------------------------------

----------------------------------------

-- Yetkili çalıştırma kontrolü
authorised_check()


---PARAMETRE ANALİZ
-- komutlar
-- kur, sil, in, gun, der, bil, ara, sor, kos

local parser = argparse("mps", "Milis Linux Paket Yöneticisi") :require_command(false)

--seçili olan komutu tespit etmek için
parser:command_target("command")

-- genel seçenekler
parser:flag "-v" "--version" :description "Sürüm bilgisi gösterir"
   :action(function() print("MPS 2.2.1 - Milis Paket Yöneticisi - Milisarge") ;os.exit(0) end)

parser:option "--renk"  :default(1)  :description "Çıktının renkli olup olmama durumunu belirler"

parser:option "--kok"    :default "/" :description "Mps işlemleri için hedef kök dizini belirtir"

parser:option "--ilkds" :args(0)     :description "Milis dosya sistemi için hedef kök dizinde ilk yapılandırmaları yapar"

parser:option "--ilk"    :args(0)     :description "Mps nin hedef kök dizinde ilk yapılandırmaları yapar"

parser:flag   "--ona"    :description "Yapılacak mps işlemi için onay verir"

parser:flag   "--debug"  :description "Yapılan işlemlerin ayrıntılı çıktısını verir"

parser:flag   "--test"   :description "Yapılan işlemlerin sadece test işlevini çalıştırır"

-- komut parametreleri

local install = parser:command "kur" :description "paket kurma işlemi" -- :action(handler)
install:argument "paket" :args("*")  :description "yerel/ağ paket girdileri"
install:option "-d" "--dosya"	     :description "dosyadan paketleri kurar"
install:option "--kurkos"  :argname "<0/1>" :default "1" :description "paket kurulum sürecince kurkos betiklerinin çalıştırma durumunu belirler"
install:option "--koskur"  :argname "<0/1>"	:default "1" :description "paket kurulum sürecince kurkos betiklerinin çalıştırma durumunu belirler"
install:option "--otokos"  :argname "<0/1>" :default "1" :description "paket kurulum sürecince kurkos betiklerinin çalıştırma durumunu belirler"
install:option "--zorla"   :args(0)         :description "zorla kurulum durumunu belirler"
install:option "--tekrar"  :args(0) 		:description "paketin yeniden kurulur"

local delete = parser:command "sil" 	:description "paket silme işlemi"
delete:argument "paket" :args("*")      :description "paket girdileri (abc def ghi)"
delete:option   "-d" "--dosya"	    	:description "dosyadan paketleri siler"
delete:option   "--kksiz" :args(0) 		:description "kurulu kontrolü yapılmaz"
delete:option   "--db"    :args(0)      :description "sadece vt kaydı silinir."

local update = parser:command "gun"     :description "güncelleme işlemleri"
update:option "-M" "--mps"     :args(0) :description "mps i günceller"
update:option "-G" "--git"     :args(0) :description "git depoları günceller"
update:option "-B" "--betik"   :args(0) :description "betik depoları günceller"
update:option "-P" "--depo"    :args(0) :description "paket depoları günceller"
update:option "-S" "--sistem"  :args(0) :description "sistemi günceller"
update:option "--sira"   :default "0" 	:description "depo sırasını belirtilir"
update:option "--paket"      :args("*") :description "ilgili paketi günceller"
update:option "--esgec" :args("*") :default "{}" :description "esgeçilecek paketleri belirtir"
update:option "--durum" :args(0)        :description "Güncelleme durum bilgisi verir. Güncelleme yapmaz."

local build = parser:command "der" 	    :description "paket derleme işlemi"
build:argument "paket" :args("*")		:description "paket girdileri (abc def ghi)"
build:option   "-d" "--dosya"	    	:description "dosyadan paketleri derler"
build:option   "--kur"    :args(0) 		:description "derledikten sonra kurar"
build:option   "-t --tek" :args(0) 		:description "gerek kontrolü yapılmadan tek paket derlenir"

local fetch = parser:command "in" 	    :description "paket indirme işlemi"
fetch:argument "paket"   :args("*")		:description "paket girdileri (abc def ghi)"
fetch:option   "-d" "--dosya"	    	:description "dosyadan paketleri indirir"
fetch:option   "--sira"  :default "1" 	:description "paketin indirileceği depo sırası belirtilir"

local search = parser:command "ara"   	:description "paket/talimat/tanım arama işlemi"
search:argument "arama"  :args("+")	    :description "arama girdisi"
search:option   "-t --talimat" :args(0) :description "talimat araması"
search:option   "-a --tanim"   :args(0) :description "tanım araması"
search:option   "--hepsi"  :default "1" :description "talimat aramada hepsinin getirilmesi"

local info = parser:command "bil"   	:description "paket bilgi işlemleri"
info:argument "paket"  :args("+")	    :description "paket girdileri"
info:option   "-g --gerek"              :description "gerek bilgileri -gc=çalışma -gd=derleme -gct=ters çalışma -gdt= ters derleme gereklerini verir"
info:option   "--kk"           :args(0) :description "paketin kurulu olma durumu"
info:option   "--kdl"          :args(0) :description "pakete ait kurulu dosya listesi"
info:option   "--pl"           :args(0) :description "pakete ait paylaşım kütüphane listesi"
info:option   "--lg"           :args(0) :description "paketin ihtiyaç duyduğu paylaşım kütüphane listesi"
info:option   "--pkd"          :args(0) :description "paketin kurulum doğrulaması yapılır"

local query = parser:command "sor"   	:description "genel sorgu işlemleri"
query:option "-L --kpl"        :args(0) :description "kurulu paket listesini verir"
query:option "--dpl"           :args(0) :description "depolardaki paket listesini verir"
query:option "--tpl"           :args(0) :description "temel paket listesini verir"
query:option "--hp" :argname "<aranan>" :args(1) :description "arama girdisinin kurulu hangi pakette olduğunu verir"
query:option "--gtl" :argname "<aranan>" :args(1) :description "arama girdisinin grubu olduğu talimat listesini verir."

local script = parser:command "kos"   	:description "paket için kur/sil/servis koşuk işlemleri"
script:argument "paket"  :args("+")	    :description "paket girdileri"
script:option   "--baskur"              :description "başlama betiğini(servis) kurar"
script:option   "--bassil"              :description "başlama betiğini(servis) siler"
script:option   "--kurkos"              :description "kurulum sonrası betiklerini çalıştırır"
script:option   "--koskur"              :description "kurulum öncesi betiklerini çalıştırır"
script:option   "--silkos"              :description "silme sonrası betiklerini çalıştırır"
script:option   "--kossil"              :description "silme öncesi betiklerini çalıştırır"

-- parametrleri tabloya al
args=parser:parse()

args_handler()

-----------------------------------------
