#!/usr/bin/python

# These dirs, along with RPMS, make up disc 2
disc2dirs = [ "Fermi" ]

# These dirs, along with RPMS, make up disc 3
disc3dirs = [ "images" , "contrib",  "misc" , "dosutils"]

# These files appear on all binary CDs
jointfiles = [ "EULA", "RPM-GPG-KEY", "README", "autorun" ]

targetSize = 645 * 1024.0 * 1024.0

# Leave about 1.2MB of space on the disc
fudgeFactor = 1.2 * 1024 * 1024

#-----------------

import sys
import os
import os.path
import string
import getopt
import time
import types

def stamp(path, releasestr, name, arch, startedAt):
    f = open("%s/.%s-%s" % (path, name, arch), "w")
    f.write("%f\n" % startedAt)
    f.write("%s %s\n" % (releasestr, name))
    f.close()

def moveFiles(srcDir, destDir, files):
    for fn in files:
	src = "%s/%s" % (srcDir, fn)
	dest = "%s/%s" % (destDir, fn)
	try:
		os.rename(src, dest)
	except:
		print "in moveFiles, src was %s, dest was %s" % (src, dest)
		raise RuntimeError

def excessFiles(path, fileList, maxSize):
    total = 0
    moveList = []
    found = 0

    for fns in fileList:
	if type(fns) == types.StringType:
	    fns = [ fns ]

	size = 0
	for fn in fns:
	    thisSize = os.path.getsize(path + "/" + fn)
	    size = size + thisSize + ((thisSize + 2047) % 2048)

	if size + total  < maxSize:
	    total = total + size
	else:
	    # once we're done, we're done
            if found == 0:
#                print "straw was %s" % (fns,)
                found = 1
	    total = maxSize
	    moveList.extend(fns)

    return moveList

class DirectoryIterator:
    def __init__(self):
        self.inodes = {}
    
    def traverse (self, arg, dirname, names):
        for name in names:
            sb = os.lstat (dirname + "/" + name)
            if not self.inodes.has_key(sb[1]):
                self.inodes[sb[1]] = sb[6]

    def total(self):
        total = 0
        for size in self.inodes.values():
            total = total + size
	return total

def spaceUsed(path):
    foo = DirectoryIterator()
    os.path.walk (path, foo.traverse, None)
    return foo.total()

startedAt = time.time()

fns = {}

(args, extra) = getopt.getopt(sys.argv[1:], '', [ 'fileorder=', 'release=' ])

if len(extra) != 2:
    print "splitdistro --fileorder <file> [--release <comment>] <toppath> <arch>"
    sys.exit(1)

releasestr = ""
packageOrderFile = None
for n in args:
    (str, arg) = n
    if str == '--fileorder':
	packageOrderFile = arg
    if str == '--release':
	releasestr = arg

if not packageOrderFile:
    print "splitdistro --fileorder <file> [--release <comment>] <toppath> <arch>"
    sys.exit(1)


arch = extra[1]
distDir = os.path.normpath(extra[0] + "/" + arch)
srcDir = os.path.normpath(extra[0] + "/SRPMS")

if not os.path.isdir(distDir):
    print "error: %s is not a directory" % distDir
    sys.exit(1)

if not os.path.isdir(srcDir):
    print "error: %s is not a directory" % srcDir
    sys.exit(1)

disc1Dir = distDir + "-disc1"
disc2Dir = distDir + "-disc2"
disc3Dir = distDir + "-disc3"
disc1SrcDir = distDir + "-disc4"
disc2SrcDir = distDir + "-disc5"
# we have leftover space on the third disc to use for sources
disc3SrcDir = distDir + "-disc3"

id = 0

files = os.listdir(distDir + "/RedHat/RPMS")
files.sort()
packages = {}
for file in files:
    l = string.split(file, ".")
    pkg = string.join(l[:-2], ".")
    if packages.has_key(pkg):
	packages[pkg].append(file)
    else:
	packages[pkg] = [ file ]

f = open(packageOrderFile, "r")
binPkgList = []
for pkg in f.readlines():
    # chop
    pkg = pkg[:len(pkg) - 1]
    if pkg[0:8] != "warning:":
	binPkgList.append(packages[pkg])

del f

print "Splitting tree..."

totalsize = spaceUsed(distDir)
print "totalsize %s" , totalsize
rpmsize = spaceUsed(distDir + "/RedHat/RPMS")
print "rpmsize %s" , rpmsize
dirsizedisc2dirs = 0
for dir in disc2dirs:
    what = distDir + "/" + dir
    if os.access(what, os.R_OK):
        dirsizedisc2dirs = dirsizedisc2dirs + spaceUsed(distDir + "/" + dir)
print "dirsizedisc2dirs %s" , dirsizedisc2dirs

dirsizedisc3dirs = 0
for dir in disc3dirs:
    what = distDir + "/" + dir
    if os.access(what, os.R_OK):
        dirsizedisc3dirs = dirsizedisc3dirs + spaceUsed(distDir + "/" + dir)

print "dirsizedisc3dirs %s" , dirsizedisc3dirs

disc1used = totalsize - rpmsize - dirsizedisc2dirs - dirsizedisc3dirs
print "disc1used %s = totalsize %s - rpmsize %s - dirsizedisc2dirs %s - dirsizedisc3dirs %s " % ( disc1used , totalsize, rpmsize, dirsizedisc2dirs, dirsizedisc3dirs)
os.system("rm -rf %s %s %s %s" % ( disc1Dir, disc2Dir, disc1SrcDir,
				   disc2SrcDir))
os.system("mkdir -p %s %s %s/SRPMS %s/RedHat/RPMS %s/RedHat/RPMS %s/SRPMS" % 
	    (disc1Dir, disc1SrcDir, disc2SrcDir, disc2Dir, 
             disc3Dir, disc3SrcDir))

print "Creating disc1..."

os.system("cp -al %s/. %s" % (distDir, disc1Dir))
stamp(disc1Dir, releasestr, "disc1", arch, startedAt)

print "Creating disc2..."
stamp(disc2Dir, releasestr, "disc2", arch, startedAt)

print "Moving disc2 only dirs"
for dir in disc2dirs:
    print "Moving %s directory to disc2 now" % (dir)
    what = disc1Dir + "/" + dir
    os.system("mv %s/ %s/" % (what , disc2Dir ))

for file in jointfiles:
    src = "%s/%s" % (disc1Dir, file)
    dest = "%s/%s" %(disc2Dir, file)
    try:
	os.link(src, dest)
    except OSError, (errno, msg):
	print "**** WARNING linking %s to %s: %s" % (src, dest, msg)

disc2pkgsize = targetSize - disc1used - fudgeFactor 
print "targetsize %s, , disc1used %s, fudgefactor %s, dirsizedisc3dirs %s" % (targetSize, disc1used, fudgeFactor , dirsizedisc3dirs )
print "disc2pkgsize" ,disc2pkgsize 

disc2pkgs = excessFiles(distDir + "/RedHat/RPMS", binPkgList, disc2pkgsize)

moveFiles("%s/RedHat/RPMS" % disc1Dir, 
	  "%s/RedHat/RPMS" % disc2Dir, 
	  disc2pkgs);
disc1Size = spaceUsed(disc1Dir)
print "disc1Size" , disc1Size

print "Creating disc3..."
stamp(disc3Dir, releasestr, "disc3", arch, startedAt)

print "Moving disc3 only dirs"
for dir in disc3dirs:
    print "Moving %s directory to disc3 now" % (dir)
    what = disc1Dir + "/" + dir
    os.system("mv %s/ %s/" % (what , disc3Dir ))

for file in jointfiles:
    src = "%s/%s" % (disc1Dir, file)
    dest = "%s/%s" %(disc3Dir, file)
    try:
	os.link(src, dest)
    except OSError, (errno, msg):
	print "**** WARNING linking %s to %s: %s" % (src, dest, msg)

disc3pkgsize = targetSize + disc1Size - disc1used - fudgeFactor - dirsizedisc3dirs
print "disc3pkgsize %s = targetsize %s + disc1Size %s - disc1used %s - fudgefactor %si - dirsizedisc3dirs %s" % (disc3pkgsize, targetSize, disc1Size, disc1used, fudgeFactor, dirsizedisc3dirs )
disc3pkgs = excessFiles(distDir + "/RedHat/RPMS", binPkgList, disc3pkgsize) 
			
moveFiles("%s/RedHat/RPMS" % disc2Dir, 
	  "%s/RedHat/RPMS" % disc3Dir, 
	  disc3pkgs);

print "Creating first source disc..."
print srcDir, disc1SrcDir
os.system("cp -al %s/. %s" % (srcDir, disc1SrcDir))
stamp(disc1SrcDir, releasestr, "disc4", arch, startedAt)

print "Creating second source disc..."
stamp(disc2SrcDir, releasestr, "disc5", arch, startedAt)

print "disc1SrcDir"
print disc1SrcDir
srcPkgList = os.listdir("%s/SRPMS" % disc1SrcDir)
srcPkgList.sort()
disc2pkgs = excessFiles(srcDir + "/SRPMS", srcPkgList,
			targetSize - fudgeFactor)
moveFiles("%s/SRPMS" % disc1SrcDir, 
	  "%s/SRPMS" % disc2SrcDir, 
	  disc2pkgs);
srcDisc1Size = spaceUsed(disc1SrcDir)

print "Dropping remainder of sources on third disc..."
disc3pkgs = excessFiles(srcDir + "/SRPMS", srcPkgList,
                        srcDisc1Size + targetSize - fudgeFactor)
moveFiles("%s/SRPMS" % disc2SrcDir,
          "%s/SRPMS" % disc3SrcDir,
          disc3pkgs)

#sys.exit(0)

sys.stdout.flush()

os.system("du -sh %s %s %s %s %s" % (disc1Dir, disc2Dir, disc3Dir,
                                     disc1SrcDir, disc2SrcDir))