#! /usr/bin/gap -q
# GAP2DEB <https://salsa.debian.org/gap-packaging-team/gap2deb>
# Copyright 2014 Bill Allombert <ballombe@debian.org>
# This program is distributed under the term of the GNU GPL2+
# The author assert no copyright interest in the output.

# require htmltotext

debhelperver := "13";

StandardsVersion := "4.7.0";

Commas:=function(list)
  return JoinStringsWithSeparator(list,", ");
end;

BaseDir:= function (path)
  local tmp, file, dir, name, ext;
  tmp :=  SplitString(path,"/");
  file:= tmp[Length(tmp)];
  Remove(tmp);
  dir := JoinStringsWithSeparator(tmp,"/");
  tmp := SplitString(file,".");
  ext := tmp[Length(tmp)];
  name := JoinStringsWithSeparator(tmp,".");
  return [dir, name, ext];
end;

Backquote:= function (prg)
  local shell, out, str;
  str := "";
  out := OutputTextString(str,true);
  Process( DirectoryCurrent(), "/bin/sh", InputTextNone(), out, ["-c", prg] );
  CloseStream(out);
  return Chomp(str);
end;

HTMLToText:=function(html)
  local shell, inp, out, str;
  str := "";
  inp := InputTextString(html);
  out := OutputTextString(str,true);
  Process(DirectoryCurrent(), "/usr/bin/html2text", inp, out,["-width","77"]);
  CloseStream(inp);
  CloseStream(out);
  return str;
end;

Email:=function(r)
  if IsBound(r.Email) then
    return Concatenation(" <",r.Email,">");
  else
    return "";
  fi;
end;

PkgName:=function(x)
  return Concatenation("gap-pkg-",LowercaseString(x));
end;

DoError:=function(s)
  Print("Error: ",s,"\n");
  QUIT_GAP(1);
end;

MakeDocBase:=function(binname, authors, abstract, docbase, Doc)
  local PackageDoc, PackageDocHTML, docid;
  PackageDoc := BaseDir(Doc.HTMLStart);
  PackageDocHTML := Concatenation(PackageDoc[1],"/*.",PackageDoc[3]);
  docid := LowercaseString(ReplacedString(Doc.BookName," ","-"));
  FileString(Concatenation("debian.gap2deb/",binname,".doc-base.",docid),Concatenation(
  "Document: gap-",docid,"\n",
  "Title: ",Doc.LongTitle,"\n",
  "Author: ",authors,"\n",
  "Abstract:\n ",abstract,"\n",
  "Section: Science/Mathematics\n",
  "\n",
  "Format: pdf\n",
  "Files: ",docbase,"/",Doc.PDFFile,"\n",
  "\n",
  "Format: HTML\n",
  "Index: ",docbase,"/",Doc.HTMLStart,"\n",
  "Files: ",docbase,"/",PackageDocHTML,"\n"));
end;

if IsBound(GAPInfo.SystemEnvironment.GAP2DEB_RULES) then
  rules:=GAPInfo.SystemEnvironment.GAP2DEB_RULES;
else
  rules:= "dh";
fi;

argv:=GAPInfo.KernelInfo.COMMAND_LINE;
argvrules:=List(Filtered(argv,s->Length(s)>=8 and s{[1..8]}="--rules="),s->s{[9..Length(s)]});

if Length(argvrules) > 0 then
  rules:=argvrules[Length(argvrules)];
fi;

if IsDirectoryPath("debian.gap2deb") then
  DoError("debian.gap2deb directory already exists");
fi;

if not IsReadableFile("PackageInfo.g") then
  DoError(Concatenation(
"file PackageInfo.g not found\n",
"gap2deb must be launched inside a GAP package source directory"));
fi;
Unbind( GAPInfo.PackageInfoCurrent );
Read("PackageInfo.g");
pkg:= GAPInfo.PackageInfoCurrent;
Unbind( GAPInfo.PackageInfoCurrent );

env:=GAPInfo.KernelInfo.ENVIRONMENT;
if IsBound(env.DEBFULLNAME) then
  maintname := env.DEBFULLNAME;
else
  maintname:=SplitString(Backquote("getent passwd $USER"),":,")[5];
fi;
if IsBound(env.DEBEMAIL) then
  maint:=Concatenation(maintname," <",env.DEBEMAIL,">");
else
  maint := maintname;
fi;

if IsReadableFile("configure") then
  arch := "any";
  multiarch := "same";
else
  arch := "all";
  multiarch := "foreign";
fi;

pkgname := LowercaseString(pkg.PackageName);
srcname := Concatenation("gap-",pkgname);
binname := Concatenation("gap-",pkgname);
synopsis := Concatenation("GAP ",pkg.PackageName," - ",pkg.Subtitle);
homepage := Concatenation("https://www.gap-system.org/Packages/",pkgname,".html");
date := Backquote("date -R");
year := Backquote("date +%Y");
copyyear := SplitString(pkg.Date,"/")[3];
if IsBound(pkg.License) then
  license := pkg.License;
  if license = "GPL-2.0-or-later" then
    license := "GPL-2+";
    gplver  := "2";
  elif license = "GPL-3.0-or-later" then
    license := "GPL-3+";
    gplver  := "3";
  elif license = "Artistic-2.0" then
    license := "Artistic-2";
  fi;
else
  license := "GPL-2+";
  gplver  := "2";
fi;
abstract :=JoinStringsWithSeparator(SplitString(HTMLToText(pkg.AbstractHTML),"\n"),"\n ");
comp :=  SplitString(pkg.ArchiveURL,"/");
archivebase := SplitString(comp[Length(comp)],"0123456789")[1];
Remove(comp);
archiveURL := JoinStringsWithSeparator(comp,"/");
authors := Commas(List(pkg.Persons,x->Concatenation(x.FirstNames," ",x.LastName)));
authoremails :=
  Commas(List(pkg.Persons,x->Concatenation(x.FirstNames," ",x.LastName,Email(x))));
pkgbaseN:=Concatenation("usr/share/gap/pkg/",pkg.PackageName);
pkgbase:=Concatenation("/",pkgbaseN);
docbaseN:=Concatenation("usr/share/doc/",binname);
docbase:=Concatenation("/",docbaseN);

gapdepver :=  ReplacedString(pkg.Dependencies.GAP,".","r");
gapdep := Concatenation("gap (",gapdepver,")");
neededslist:=List(pkg.Dependencies.NeededOtherPackages,x->PkgName(x[1]));
suggestionslist := List(pkg.Dependencies.SuggestedOtherPackages,x->PkgName(x[1]));
conditionslist := List(pkg.Dependencies.ExternalConditions,x->x);
Doc := pkg.PackageDoc;
if not IsList(Doc) then
  Doc := [ Doc ];
fi;
Depends:=Concatenation("Depends: ",
  Commas(Concatenation(["${misc:Depends}", gapdep],neededslist,conditionslist)),"\n");
if IsEmpty(suggestionslist) then
  Suggests:="";
else
  Suggests:=Concatenation("Suggests: ",Commas(suggestionslist),"\n");
fi;

CreateDir("debian.gap2deb");
CreateDir("debian.gap2deb/source");
CreateDir("debian.gap2deb/patches");
FileString("debian.gap2deb/source/format","3.0 (quilt)\n");

if IsReadableFile("debian/changelog") then
  Exec("cp debian/changelog debian.gap2deb/changelog");
else
  FileString("debian.gap2deb/changelog",Concatenation(
  srcname," (",pkg.Version,"-1) unstable; urgency=low\n",
  "\n",
  "  * Initial Release.\n",
  "  * This is part of the GAP system.\n",
  "\n",
  " -- ",maint,"  ",date,"\n"));
fi;
FileString("debian.gap2deb/control",Concatenation(
"Source: ",srcname,"\n",
"Section: math\n",
"Priority: optional\n",
"Maintainer: ",maint,"\n",
"Build-Depends: debhelper-compat (= ",debhelperver,"), gap (>= 4r7), gap-doc\n",
"Standards-Version: ",StandardsVersion,"\n",
"Rules-Requires-Root: no\n",
"Homepage: ",homepage,"\n",
"\n",
"Package: ",binname,"\n",
"Provides: gap-pkg-",pkgname,"\n",
Depends,
"Recommends: gap\n",
Suggests,
"Multi-Arch: ",multiarch,"\n",
"Architecture: ",arch,"\n",
"Description: ",synopsis,"\n",
" GAP is a system for computational discrete algebra, with particular emphasis\n",
" on Computational Group Theory. GAP provides a programming language, a library\n",
" of thousands of functions implementing algebraic algorithms written in the GAP\n",
" language as well as large data libraries of algebraic objects. GAP is used in\n",
" research and teaching for studying groups and their representations, rings,\n",
" vector spaces, algebras, combinatorial structures, and more.\n",
" .\n",
" ",abstract,"\n"));

if IsBound(pkg.SourceRepository) then
  FileString("debian.gap2deb/watch",Concatenation(
"version=4\n",
"opts=filenamemangle=s/.+\\/v?([\\.\\d]+)\\.tar\\.gz/",LowercaseString(pkg.PackageName),"-$1\\.tar\\.gz/,\\\n",
"downloadurlmangle=s/archive\\/refs\\/tags\\/v([\\.\\d]+)\\.tar\\.gz/releases\\/download\\/v$1\\/",LowercaseString(pkg.PackageName),"-$1\\.tar\\.gz/ \\\n",
"  ",pkg.SourceRepository.URL,"/tags .*/v?([\\.\\d]+)\\.tar\\.gz debian uupdate\n"));
else
  FileString("debian.gap2deb/watch",Concatenation(
"version=3\n",
archiveURL,"/",archivebase,"([0-9].*)\\.tar\\.gz debian uupdate\n"));
fi;

for doc in Doc do
  MakeDocBase(binname, authors, abstract, docbase, doc);
od;

copyrighttext := Concatenation(
"Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\n",
"Upstream-Name: ",pkg.PackageName,"\n",
"Source: ",pkg.PackageWWWHome,"\n",
"\n",
"Files: *\n",
"Copyright: Copyright ",copyyear," ",authoremails,"\n",
"License: ",license,"\n",
"\n",
"Files: debian/*\n",
"Copyright: Copyright ",year," ",maint,"\n",
"License: ",license,"\n",
"\n",
"License: ",license,"\n");

if IsBound(gplver) then
  copyrighttext := Concatenation(copyrighttext,
" This program is free software: you can redistribute it and/or modify\n",
" it under the terms of the GNU General Public License as published by\n",
" the Free Software Foundation, either version ",gplver," of the license, or\n",
" (at your option) any later version.\n",
" .\n",
" This program is distributed in the hope that it will be useful,\n",
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n",
" GNU General Public License for more details.\n",
" .\n",
" You should have received a copy of the GNU General Public License\n",
" along with this program. If not, see <https://www.gnu.org/licenses/>.\n",
" .\n",
" On Debian systems, the full text of the GNU General Public\n",
" License version ",gplver," can be found in the file\n",
" `/usr/share/common-licenses/GPL-",gplver,"'.\n");
fi;

FileString("debian.gap2deb/copyright", copyrighttext);

FileString("debian.gap2deb/links", Concatenation(
  List(Doc,doc->Concatenation(pkgbase,"/",doc.ArchiveURLSubset[1]," ",
       docbaseN,"/",doc.ArchiveURLSubset[1],"\n"))));

FileString("debian.gap2deb/patches/series", "doc-makefile\n");
FileString("debian.gap2deb/patches/doc-makefile", Concatenation(
"Index: ",srcname,"/doc/Makefile\n",
"===================================================================\n",
"--- /dev/null   1970-01-01 00:00:00.000000000 +0000\n",
"+++ ",srcname,"/doc/Makefile      2013-07-27 23:11:04.365369025 +0200\n",
"@@ -0,0 +1,38 @@\n",
"+SHELL=/bin/bash\n",
"+pkgdocdir=",pkgbase,"/doc\n",
"+DOCDIR=$(DESTDIR)$(pkgdocdir)\n",
"+MANUAL=main\n",
"+DIRS=.\n",
"+doc:\n",
"+\t./make_doc\n",
"+clean:\n",
"+\trm -f $(DIRS)/*.{html,txt,css,js}\n",
"+\trm -f $(DIRS)/make_manuals.out $(DIRS)/mathjax\n",
"+\trm -f $(DIRS)/$(MANUAL).{aux,bbl,blg,brf,idx,ilg,ind,log,out,pnr,tex,toc,toc.gz}\n",
"+\trm -f $(DIRS)/manual{,-bw}.{lab,six,six.gz,pdf}\n",
"+\trm -f manualbib.xml.bib\n",
"+install: install-pdf install-help install-html\n",
"+install-pdf:\n",
"+\ttest -d $(DOCDIR)/$(DIRS) || install -d $(DOCDIR)/$(DIRS)\n",
"+\tset -e; for man in $(DIRS); do \\\n",
"+\t  install -m 0644 $$man/manual.pdf $(DOCDIR)/$$man;\\\n",
"+\tdone\n",
"+install-help:\n",
"+\ttest -d $(DOCDIR)/$(DIRS) || install -d $(DOCDIR)/$(DIRS)\n",
"+\tset -e; for man in $(DIRS); do \\\n",
"+\t  gzip --best --no-name $$man/manual.six; \\\n",
"+\t  gzip --best --no-name $$man/$(MANUAL).toc; \\\n",
"+\t  install -m 0644 $$man/$(MANUAL)bib.xml $(DOCDIR)/$$man; \\\n",
"+\t  install -m 0644 $$man/$(MANUAL)bib.xml.bib $(DOCDIR)/$$man; \\\n",
"+\t  install -m 0644 $$man/$(MANUAL).toc.gz $(DOCDIR)/$$man; \\\n",
"+\t  install -m 0644 $$man/manual.six.gz $(DOCDIR)/$$man; \\\n",
"+\t  install -m 0644 $$man/manual.lab $(DOCDIR)/$$man; \\\n",
"+\t  install -m 0644 $$man/*.txt $(DOCDIR)/$$man; \\\n",
"+\tdone\n",
"+install-html:\n",
"+\ttest -d $(DOCDIR)/$(DIRS) || install -d $(DOCDIR)/$(DIRS)\n",
"+\tset -e; for man in $(DIRS); do \\\n",
"+\t  install -m 0644 $$man/*.{html,css,js} $(DOCDIR)/$$man;\\\n",
"+\t  ln -s `readlink mathjax` $(DOCDIR)/$$man/mathjax;\\\n",
"+\tdone\n",
"+.PHONY: clean install install-pdf install-help install-html\n"));

readme:="";
if IsReadableFile("README") then
  readme:="README";
elif IsReadableFile("README.md") then
  readme:="README.md";
elif IsReadableFile("README.txt") then
  readme:="README.txt";
fi;
changes:="";
if IsReadableFile("CHANGES") then
  changes:=" CHANGES";
elif IsReadableFile("CHANGES.md") then
  changes:=" CHANGES.md";
elif IsReadableFile("CHANGES.txt") then
  changes:=" CHANGES.txt";
fi;

excludeddir:=["debian","debian.gap2deb","doc","tst","htm"];
installdir:=JoinStringsWithSeparator(
  Difference(Filtered(DirectoryContents("."),
  x->IsDirectoryPath(x) and x[1] <> '.'), excludeddir), " ");

testfile:=false;
if IsBound(pkg.TestFile) then
  testfile:=pkg.TestFile;
elif IsReadableFile("tst/testinstall.g") then
  testfile:="tst/testinstall.g";
elif IsReadableFile("tst/testall.g") then
  testfile:="tst/testall.g";
fi;

if testfile = false then
  dotest:="";
  cleantest:="";
else
  if rules = "dh" then
    target:= "execute_after_dh_auto_test:\n";
  else
    target:= "";
  fi;
  dotest:= Concatenation(
"ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))\n",
  target,
"\techo 'SetPackagePath(\"",pkg.PackageName,"\",\".\"); Read(\"",testfile,"\");' \\\n",
"\t| gap -q -R -A | tee debian/gap.tst\n",
"\tgrep -q \"^#I  No errors detected while testing\" debian/gap.tst\n",
"endif\n");
  cleantest:= "\trm -f debian/gap.tst\n";
fi;

docfile := false;
if IsReadableFile("makedoc.g") then
  docfile:="makedoc.g";
elif IsReadableFile("makedocrel.g") then
  docfile:="makedocrel.g";
fi;

if docfile = false then
  dodoc:="\tmake -C doc\n";
else
  if rules = "dh" then
    target:= "execute_after_dh_auto_build:\n";
    endrules:="";
  else
    target:= "";
    endrules:= " && touch build-indep-stamp";
  fi;
  dodoc:= Concatenation(
  target,
"\techo 'SetPackagePath(\"",pkg.PackageName,"\",\".\"); PushOptions(rec(relativePath:=true)); Read(\"",docfile,"\");' \\\n",
"\t| gap -q -R -A",
  endrules
,"\n");
fi;

if rules = "dh" then
  FileString("debian.gap2deb/rules", Concatenation(
"#!/usr/bin/make -f\n",
"# Copyright ",year," ",maint,"\n",
"\n",
"export SOURCE_DATE_EPOCH = $(shell date -d \"$$(dpkg-parsechangelog -SDate)\" +%s)\n",
"export FORCE_SOURCE_DATE = 1\n",
"export LC_ALL = C\n",
"\n",
dotest,
"\n",
dodoc,
"\n",
"override_dh_install:\n",
"\tdh_install *.g ",installdir," ",pkgbaseN,"\n",
"\tmake -C doc install DESTDIR=../debian/",binname,"\n",
"\n",
"override_dh_installdocs:\n",
"\tdh_installdocs ",readme,"\n",
"\n",
"override_dh_installchangelogs:\n",
"\tdh_installchangelogs ",changes,"\n",
"\n",
"override_dh_clean:\n",
"\tmake -C doc clean\n",
cleantest,
"\tdh_clean\n",
"\n",
"%:\n",
"\tdh $@\n",
"\n",
".PHONY: execute_after_dh_auto_test execute_after_dh_auto_build clean override_dh_install override_dh_clean override_dh_installdocs override_dh_installchangelogs \n"));
else
 FileString("debian.gap2deb/rules", Concatenation(
"#!/usr/bin/make -f\n",
"# Copyright ",year," ",maint,"\n",
"\n",
"export SOURCE_DATE_EPOCH = $(shell date -d \"$$(dpkg-parsechangelog -SDate)\" +%s)\n",
"export FORCE_SOURCE_DATE = 1\n",
"export LC_ALL = C\n",
"\n",
"build-indep-stamp:\n",
dotest,
dodoc,
"build-indep: build-indep-stamp\n",
"build-arch:\n",
"build: build-indep\n",
"\n",
"clean:\n",
"\tdh_testdir\n",
"\tdh_testroot\n",
"\tmake -C doc clean\n",
"\trm -f build-indep-stamp\n",
cleantest,
"\tdh_clean\n",
"\n",
"install: build\n",
"\tdh_testdir\n",
"\tdh_testroot\n",
"\tdh_prep\n",
"\tdh_installdirs\n",
"\tdh_install *.g ",installdir," ",pkgbaseN,"\n",
"\tmake -C doc install DESTDIR=../debian/",binname,"\n",
"binary-arch: build-arch\n",
"binary-indep: build-indep install\n",
"\tdh_testdir\n",
"\tdh_testroot\n",
"\tdh_installdocs ",readme,"\n",
"\tdh_installexamples\n",
"\tdh_installchangelogs",changes,"\n",
"\tdh_link\n",
"\tdh_compress\n",
"\tdh_fixperms\n",
"\tdh_installdeb\n",
"\tdh_gencontrol\n",
"\tdh_md5sums\n",
"\tdh_builddeb\n",
"\n",
"binary: binary-indep binary-arch\n",
".PHONY: build clean binary-indep binary-arch binary install configure\n"));
fi;


if not IsDirectoryPath("debian") then
  Process(DirectoryCurrent(), "/bin/mv", InputTextNone(), OutputTextNone(),
          ["debian.gap2deb","debian"]);
fi;

QUIT_GAP(0);
