#!/bin/sh
#
# Copyright 2013, Intel Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
# native

#author: Ronan Le Martret ronan@fridu.net


WORKINGDIR="/tmp/obs"
OBS_API=
OSC_CMD="osc"
RM_CMD="rm -fr"
XMLLINT=$(which xmllint)

DRYRUN=

#Source the default parameter for update_project.
if [ -f "${HOME}/.update_projectrc" ] ; then
   echo source ${HOME}/.update_projectrc
   echo OSC_CMD $OSC_CMD
   source ${HOME}/.update_projectrc
else
   #If .update_projectrc is create create empty file.
   echo No file ${HOME}/.update_projectrc, create it.
   touch ${HOME}/.update_projectrc
   echo '#set the WORKINGDIR  for update_project'
   echo 'WORKINGDIR="/tmp/obs"' >> ${HOME}/.update_projectrc
   echo '# set the OBS API'
   echo 'OBS_API=' >> ${HOME}/.update_projectrc
fi

#If no OBS_API exit.
if  [ -z "${OBS_API}" ] ; then
  echo no API configurate for the OBS, please set OBS_API parameter.
  exit 1
fi

#if no xmllint, exit
if [ -z "${XMLLINT}" ]; then
	echo "Please install xmllint"
	exit 1
fi

#Create the WORKINGDIR directory.
if [ ! -d ${WORKINGDIR} ] ; then
    mkdir -p ${WORKINGDIR}
fi

pushd ${WORKINGDIR}

#check the list of project.
if [ $# -eq 0 ] ; then
   PROJECT_LIST=$(update_project_manager list_project)
else
   PROJECT_LIST="$@"
fi

if [ ! $? == 0 ] ; then
  echo command \"update_project_manager list_project\" failed.
  exit 1
fi

for PROJECT in ${PROJECT_LIST}; do

  if [ ! -d ${WORKINGDIR}/${PROJECT} ] ; then
    echo checkout project ${PROJECT}
    ${OSC_CMD} -A ${OBS_API} co ${PROJECT}
    cd ${PROJECT}
  else
    cd ${PROJECT}
    echo update project ${PROJECT}
    #update all the project package.
    ${OSC_CMD} up
  fi

  # check if the project is disable.
  osc meta prj ${PROJECT} > /tmp/meta_prj
  PROJECT_WAS_DISABLE=`update_project_manager project_is_disable /tmp/meta_prj`
  ${RM_CMD} /tmp/meta_prj

  PROJECT_IS_DISABLE=
  if [ -z ${DRYRUN} ] ; then
      if [ -z ${PROJECT_WAS_DISABLE} ] ;then
        #if the is not already disable, disable it.
        ${OSC_CMD} api -X POST "/source/${PROJECT}/?cmd=set_flag&flag=build&status=disable"
        PROJECT_IS_DISABLE="yes"
      fi
  fi
  #Before update do an check and store the current package
  OLD_PKG_LIST=`ls | grep -v .osc`
  cd ..

  #ARCH is optional
  ARCH=`update_project_manager get_arch ${PROJECT}`

  #Get the manifest list from conf file
  MANIFEST_LIST=`update_project_manager get_manifest_list ${PROJECT}`
  if [ ! $? == 0 ] ; then
    echo command \"update_project_manager get_manifest_list ${PROJECT}\" failed.
    [ -n "${PROJECT_IS_DISABLE}" ] && ${OSC_CMD} api -X POST "/source/${PROJECT}/?cmd=set_flag&flag=build&status=enable"
    exit 1
  fi

  echo
  echo get alias file
  #The alias file is a simply text file, each line begin with a package name,
  #{PKG} follow by package alias {PKG_ALIAS_1} {PKG_ALIAS_2} {PKG_ALIAS_3} ...
  echo update_project_manager get_alias_file ${PROJECT}
  ALIAS_FILE=$(update_project_manager get_alias_file ${PROJECT} )
  BLACKLIST_FILE=$(update_project_manager get_blacklist_file ${PROJECT} )
  CONSTRAINTS_FILE=$(update_project_manager get_constraints_file ${PROJECT} )

  #If the Manifest is a project URL download it.
  if [[ ${ALIAS_FILE} =~ ^http.*$ ]] ; then
    curl -L ${ALIAS_FILE} > ${WORKINGDIR}/$(basename ${ALIAS_FILE})
    ALIAS_FILE=${WORKINGDIR}/$(basename ${ALIAS_FILE})
  fi
  if [ -n  "${ALIAS_FILE}" ] ; then
      ALIAS_FILE=" --alias ${ALIAS_FILE}"
  fi

  #If the Manifest is a project URL download it.
  if [[ ${BLACKLIST_FILE} =~ ^http.*$ ]] ; then
    curl -L ${BLACKLIST_FILE} > ${WORKINGDIR}/$(basename ${BLACKLIST_FILE})
    BLACKLIST_FILE=${WORKINGDIR}/$(basename ${BLACKLIST_FILE})
  fi
  if [ -n  "${BLACKLIST_FILE}" ] ; then
      BLACKLIST_FILE=" --blacklist ${BLACKLIST_FILE}"
  fi

  #If the constraints is an URL download it.
  if [[ ${CONSTRAINTS_FILE} =~ ^http.*$ ]] ; then
    curl -L ${CONSTRAINTS_FILE} > ${WORKINGDIR}/$(basename ${CONSTRAINTS_FILE})
    CONSTRAINTS_FILE=${WORKINGDIR}/$(basename ${CONSTRAINTS_FILE})
  fi

  MANIFEST_FILES_LIST=""
  MANIFEST_DIR=${WORKINGDIR}"/update_"${PROJECT}
  mkdir -p ${MANIFEST_DIR}
  for MANIFEST in ${MANIFEST_LIST} ; do
    #Get the Manifest file or a project URL.
    echo update_project_manager get_manifest_file ${PROJECT} ${MANIFEST}
    MANIFEST_FILE=`update_project_manager get_manifest_file ${PROJECT} ${MANIFEST}`
    if [ ! $? == 0 ] ; then
      echo command \"update_project_manager get_manifest_file ${PROJECT} ${MANIFEST}\" failed.
	  [ -n "${PROJECT_IS_DISABLE}" ] && ${OSC_CMD} api -X POST "/source/${PROJECT}/?cmd=set_flag&flag=build&status=enable"
      exit 1
    fi
    #If the Manifest is a project URL download it.
    if [[ ${MANIFEST_FILE} =~ ^http.*$ ]] ; then
      LOCAL_MANIFEST_FILE=${MANIFEST_DIR}"/"${MANIFEST}".xml"
      download_manifest ${LOCAL_MANIFEST_FILE} ${MANIFEST_FILE} ${ARCH}
      MANIFEST_FILE=${LOCAL_MANIFEST_FILE}
    fi

	if [[ ! -f "$MANIFEST_FILE" ]]; then
		echo "Downloading manifest $MANIFEST failed."
		exit 1
	fi

    echo

    # check manifest file
    if ! xmllint --noout ${MANIFEST_FILE}; then
      echo "Manifest check failed: ${MANIFEST_FILE}"
      exit 1
    fi

    echo "    add manifest: ${MANIFEST_FILE}"
    echo
    MANIFEST_FILES_LIST="${MANIFEST_FILES_LIST} ${MANIFEST_FILE}"

  done
  mkdir -p "${MANIFEST_DIR}/main_manifest"
  MAIN_MANIFEST="${MANIFEST_DIR}/main_manifest/${PROJECT}_$(date +"%Y%m%d_%H%M%S").xml"

  MERGE_CMD="update_project_manager merge_project_manifest"

  echo  update_project_manager merge_project_manifest ${BLACKLIST_FILE} ${ALIAS_FILE} --manifest_dst ${MAIN_MANIFEST} ${MANIFEST_FILES_LIST}
  update_project_manager merge_project_manifest ${BLACKLIST_FILE} ${ALIAS_FILE} --manifest_dst ${MAIN_MANIFEST} ${MANIFEST_FILES_LIST}
  if [[ $? -ne 0 ]]; then
	echo "update_project_manager merge_project_manifest failed. Skipping project"
	continue
  fi

  NEW_PKG_LIST=$(update_project_manager list_package ${MAIN_MANIFEST})

  #the main part of the script. Generate the service file.
  echo Generate service file into ${WORKINGDIR}/${PROJECT} directory.
  echo $(pwd)
  echo update_project_manager  create_package_from_manifest --project_dir ${WORKINGDIR}/${PROJECT} ${MAIN_MANIFEST}
  update_project_manager  create_package_from_manifest --project_dir ${WORKINGDIR}/${PROJECT} ${MAIN_MANIFEST}
  if [[ $? -ne 0 ]]; then
	echo "update_project_manager create_package_from_manifest failed. Skipping project"
	continue
  fi

  echo check new package into project ${PROJECT}.
  cd ${PROJECT}
  for new_package in `osc status | grep '?' | cut -d ' ' -f 5`;do
    #add new package.
    echo ${OSC_CMD} add ${new_package};
    ${OSC_CMD} add ${new_package};
  done

  #check the package need to be deleted.
  echo ${OLD_PKG_LIST} | tr ' ' '\n' | sort > /tmp/old_pkg_file.txt
  echo ${NEW_PKG_LIST} | tr ' ' '\n' | sort > /tmp/new_pkg_file.txt
  PACKAGE_TO_DEL=`comm -23  /tmp/old_pkg_file.txt /tmp/new_pkg_file.txt`
  ${RM_CMD} /tmp/old_pkg_file.txt
  ${RM_CMD} /tmp/new_pkg_file.txt

  if [ -z "${DRYRUN}" ] ; then
      for old_package in ${PACKAGE_TO_DEL} ; do
        #remove unused package (only if not an aggregate).
        if [[ -f "${old_package}/_aggregate" ]]; then
           echo "Keeping aggregate package ${old_package}"
        else
           echo ${OSC_CMD} rm ${old_package};
           ${OSC_CMD} rm ${old_package};
        fi
      done
  fi

  # generate build constraints
  if [[ -n "$CONSTRAINTS_FILE" ]]; then
    echo "Applying constraints"
    sed 's/#.*$//g' ${CONSTRAINTS_FILE} | while read pkgname label; do
        [[ -z "$pkgname" ]] && continue
        if [[ -z "$label" ]]; then
            echo "Invalid constraint for package $pkgname: invalid label"
            continue
        fi

        if [[ ! -d $pkgname ]]; then
            echo "Skipping constraint for non existing package $pkgname"
            continue
        fi

        # generate constraint file
        echo "Generating constraints for $pkgname"
        [[ -z "$DRYRUN" ]] && cat <<EOF >$pkgname/_constraints
<constraints> 
  <hostlabel>$label</hostlabel>
</constraints>
EOF
    done
  fi

  #commit all change
  [ -z "${DRYRUN}" ] && ${OSC_CMD} commit -m "- commit update_project `date` ."

  #Finaly enable the project.
  [ -n "${PROJECT_IS_DISABLE}" ] && ${OSC_CMD} api -X POST "/source/${PROJECT}/?cmd=set_flag&flag=build&status=enable"

  cd ..
done

popd
