#!/usr/bin/python3
 

# This script is free to copy and use. Absolutely no guarantees provided
# or responsibility taken 

import inspect,sys,copy,os,tempfile,glob
import subprocess as sp

def pdn(*p):
  pass

#pd=pdn  # comment out to disable debug output   

ch_lf=chr(0xa)

def glnsb2(ff):
  gg=inspect.getouterframes(ff)
  lns=[]
  fls=[]
  for framer in gg:
    iii=inspect.getmembers(framer[0])
    for df in iii:
      if df[0]=='f_lineno':
        lns.append(df[1])
      elif df[0]=='f_globals':
        if df[1].__contains__('__file__'):
          fls.append(df[1]['__file__'])   
        else: 
          fls.append('no_file')   
  return lns[1:],fls[1:]

def glns2():
# get line numbers from stack
  ff=inspect.currentframe()
  return glnsb2(ff)

def pl_s(c=0):
  c+=1
  ds=glns2()
  return (str(ds[0][c]),str(ds[1][c]))

def pd(*p):    # print debug output with line number
    s=pl_s(c=1)
    print(s[0],st_split(s[1],os.sep)[-1],p)

pe=pd

def st_join(*p):   # string join with python2 format
  if len(p)==0:
    return ' '.join(slist)
  return p[1].join(p[0])  

def st_lower(s):
  return s.lower()

def st_upper(s):
  return s.upper()

def st_split(*p):  #python 2 style split
  if len(p)==2:
    return (p[0].split(p[1]))
  else:
    return (p[0].split())


def chopr(str,txt):
# return text (left,right) of txt split rightmost
  j=str.split(txt)
  if len (j)>1:
    return (txt.join(j[0:-1]),j[-1])
  elif len (j)==1:
    return j
  else:
    return str  




def fl_writebya(filnam, data):
    fo = open(filnam, 'wb')
    fo.write(data)
    fo.close()



def parsplit(pr): # Break up params according to unix shell conventions
  d=copy.copy(pr)
  mips=[]
  orps=[]
  eqps=[]
  inmips=True
  ineql=True
  for p in d:
    pd(p)
    se=st_split(p,'=')
    if p=='-':
      inmips=False
    elif  p=='=':
      pd()
      ineql=False
    elif inmips and p[0]=='-':
      mips += [p]
    elif ineql and (len(se)>1):
      eqps += [(se[0],st_join(se[1:],'='))]
    else:
      orps += [p]
  return (orps,mips,eqps,pr)    

class emp():
  pass

  
def fl_tempdir():
    d = tempfile.mktemp()
    os.mkdir(d)
    return d


def fl_write(filnam, data):
    fo = open(filnam, 'w')
    for line in data:
#        fo.write((mkk00(line) + ch_lf))
        fo.write((line + ch_lf))
    fo.close()



def xeccmd(*args):
# execute command by invoking a shell - xecprog([prog],stdin data]) returns [stdout,stderr]
  progname=args[0]
  if len (args)>1:
    inp=args[1]
  else:
    inp=[]
  p=sp.Popen(progname,shell=True,stdin=sp.PIPE,stdout=sp.PIPE,stderr=sp.PIPE,universal_newlines=True, close_fds=True)
  r=p.communicate(input=None)
  return (r[0].split(ch_lf),r[1].split(ch_lf))



def parsplit(pr): # Break up params according to unix shell conventions
  d=pr[:]
  mips=[]


  orps=[]
  eqps=[]
  inmips=True
  ineql=True
  for p in d:
    se=st_split(p,'=')
    if p=='-':
      inmips=False
    elif  p=='=':
      ineql=False
    elif inmips and p[0]=='-':
      mips += [p]
    elif ineql and (len(se)>1):
      eqps += [(se[0],st_join(se[1:],'='))]
    else:
      orps += [p]
  return (orps,mips,eqps,pr)    

devemp=0
devgpt=1
devmbr=2

def devtype(dev):
  s= 'echo q | sudo gdisk '+dev 
  r=xeccmd(s)
  res=devemp
  for line in r[0]:
    if 'GPT: present' in line:
      res=devgpt
      break
    elif 'GPT: not present' in line:
      res=devmbr
      break
  return res    

def main():
  p=parsplit(sys.argv[1:])
  dev=p[0][0]
  pd(devtype(dev))    


def needpkg(deps):
#  print (deps)
  s=xeccmd('dpkg -l')
  plist=[]
  for l in s[0]:
    if l[0:2]=='ii':
#      print(l.split()[1]) 
      l2=l.split()[1]
      l3=st_split(l2,':')[0]
#      pd(l3)
      plist.append(l3)
  missing=[]    
  for dep in deps:
    if not dep in plist:
      missing.append(dep)
#  st_join(missing,' ')   
  return missing

  

#   Text to pipe into utilities   

chrtit="""
df
apt update
apt upgrade
echo "RESUME=none" > /etc/initramfs-tools/conf.d/resume  
update-initramfs -u
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck --no-nvram --removable $DEVICE
update-grub
"""



hlptxt="""   


debclone : build installed debian  disk/device

packages required:
  parted,utils-linux,grub-efi,initramfs-tools,syslinux,fdisk,gdisk,sudo

Target disk will be formatted with two partitions:
  1:  /boot/efi  Bios boot 300M
  2:  /          Ext4 Remainder of disk

apt upgrade and initramfs are performed on the target device. File /etc/fstab is generated for the target disk using the UUID.
These operations are needed to ensure the target device  is independently bootable.
  
No swap partition is made, assuming a swapfile is to be used

debclone clones files mounted on "/" to target
eg:
   debclone -v op=clone /dev/sda
clones partition mounted  on / to /dev/sda2 and installs grub boot to /dev/sda1
   debclone -dv op=clone /dev/sda  # dummy run

options:
-v   : verbose
-d   : dummy
+m   : Genrate old style MBR boot.

Operations:

op=clone or op=build :

carries out entire installation of files and boot
there are also subsidiary partial operations for debugging.
Be vary careful using these

op=ptn   partitions target device
op=copy  copies files to target
op=tog   sets up device mounting for chroot and grub intstallation 
op=grub  executes chroot on target partition
op=frog  unmounts mounted devices and directories
op=dummy simply lists operations

           CAUTION , NB
This script requires full sudo root permissions with no password
It is quite capable of wrecking a partition and needs careful use.
Run first with -dv options and check commands.

I take absolutely no responsibilty for its usage.

Examples:

1:
debclone -v op=clone /dev/sdb
# make bootable usb stick on sdb, root is on pc

2:
debclone -v op=clone /dev/sda   
# install os and files from booted usb  stick on sdb to pc's sda

"""
ftxt="""
p

d

d

d

o
n
p
1

+200M
t
c
n 
p
2


a
1
p
wq
"""

sysltxt="""
PROMPT 1
timeout 10

DEFAULT linuxmb
    SAY Now booting a kernel from SYSLINUX...

LABEL linux
    linux /vmlinuz
    initrd /initrd.img
    append root=/dev/ram0 rw

label linuxmb
    linux /vmlinuz
    initrd /initrd.img
    append root=/dev/sdb2 ro

label linuxma
    linux /vmlinuz
    initrd /initrd.img
    append root=/dev/sda2 ro

"""

######################## end of utility inputs



if __name__ == '__main__':
  main()
 
