#!/usr/bin/env bash cd src if [ -f debian/changelog ] || [ ! -d .git ]; then tamarin_info "Not a Git repository or Debian changelog already exists !" exit else tamarin_info "Creating changelog with commits information." fi # Get pkg tags as tie points in commit history pkg_tags="$(git for-each-ref --format '%(refname)' refs/tags | tac)" # Set starting commit ceiling_commit=$(git describe --match "build/*" --abbrev=0 2>/dev/null) if [ -z "$ceiling_commit" ] then ceiling_commit="HEAD" fi first_commit=$(git rev-list --max-parents=0 HEAD) # Get commits log as changelog current_release_tag=$(git describe --match "release/*" --abbrev=0 2>/dev/null) if [[ -z ${current_release_tag} ]] then tamarin_warn "No release tag found, you repo should have a tag like 'release/*'" tamarin_info "Assuming tag release/0.0.0 on first commit of branch master" current_release="release/0.0.0" current_release_tag=${first_commit} else current_release=$current_release_tag fi touch debian/changelog project_name=$(tamarin_db get project_name) distribution=$(tamarin_db get distribution UNRELEASED) urgency=$(tamarin_db get urgency low) package_level=$(tamarin_db get package_level dev) function get_hash { # Return commit hash from various pointer pointer="$1" echo "$(git log -n1 --format=%H ${pointer})" } function get_short_hash { # Return commit short hash from various pointer pointer="$1" echo "$(git log -n1 --format=%h ${pointer})" } function get_previous_pkg_tag { # Return previous pkg/* tag or current tag if no previous pkg/* exists. commit="$1" echo "$(git describe --abbrev=0 --match='pkg/*' $commit 2>/dev/null)" } function parse_tag { tag="$1" flavor="${tag%%/*}" extended_version="${tag##*/}" if [ "$flavor" = "pkg" ] then exploded_version="$(echo $extended_version | sed "s/\([a-z0-9.]\+\)-\([0-9]\+\)\(-[a-z]\++[0-9]\+\)\?\(-\([0-9]\+\)-\(g[a-z0-9]\+\)\)\?$/version:\1 revision:\2 modification:\3 distance:\5 anchor:\6/")" elif [ "$flavor" = "release" ] then exploded_version="$(echo $extended_version | sed "s/\([a-z0-9.]\+\)\(-\([0-9]\+\)-\(g[a-z0-9]\+\)\)\?$/version:\1 distance:\3 anchor:\4/")" fi echo $exploded_version } function get_distance_from_tag { description_tag="$1" tag=${description_tag%-*-*} anchor="$2" if [[ "$(get_hash $tag)" =~ "$(get_hash $anchor)" ]] then echo 0 else distance="$(parse_tag $description_tag)" distance="${distance#*distance:}" distance="${distance%% *}" echo $distance fi } function get_upstream_version_from_tag { tag="$1" upstream="$(parse_tag $tag)" upstream="${upstream#*version:}" upstream="${upstream%% *}" echo "$upstream" } function get_package_version_from_tag { tag="$1" package="$(parse_tag $tag)" package="${package#*revision:}" package="${package%% *}" echo "$package" } function get_distribution_from_tag { # tag pkg like pkg/// # may be composed tag="$1" distribution="${tag#pkg/*/}" distribution="${distribution%/*}" distribution="${distribution/\//-}" echo $distribution } function get_previous_release_tag { # Return previous pkg/* tag or current tag if no previous pkg/* exists. commit="$1" echo "$(git describe --abbrev=0 --always --match='release/*' $commit)" } function on_pkg_tag { # Return 1 if current commit is tagged with pkg/* tag. commit="$1" nearest_old_pkg_tag="$(get_previous_pkg_tag $commit)" if [ -n "${nearest_old_pkg_tag}" ] && [ "$(get_hash ${commit})" = "$(get_hash ${nearest_old_pkg_tag})" ] then return 0 else return 1 fi } function next_step { # Return previous pkg/* tag or first commit if no pkg/* tag exists commit="$1" if [ "$(get_hash $commit)" = "$(get_hash $first_commit)" ] then echo $commit elif on_pkg_tag $commit then nearest_old_pkg_tag="$(get_previous_pkg_tag ${commit}^1)" else nearest_old_pkg_tag="$(get_previous_pkg_tag ${commit})" fi if [[ "$nearest_old_pkg_tag" =~ 'pkg/' ]] then echo $nearest_old_pkg_tag else echo $first_commit fi } function date_from_commit { # Return date suitable for changelog entry signature commit="$1" if [ "$(get_hash ${commit})" = "$(get_hash HEAD)" ] then package_date=$(date --rfc-2822) else maintainer_commit="$(get_previous_pkg_tag $commit)" package_date="$(git tag -l --format='%(creator)' ${maintainer_commit})" package_date="${package_date##*> }" package_date="$(date --rfc-2822 -d @${package_date% *})" fi echo "$package_date" } function packager_from_commit { # Return Name id format, suitable for changelog entry signature commit="$1" if on_pkg_tag "${commit}" then maintainer_commit="$(get_previous_pkg_tag $commit)" maintainer="$(git tag -l --format='%(creator)' ${maintainer_commit})" maintainer="${maintainer%>*}>" else maintainer="$(git log -n1 --format='%cn <%ce>')" fi maintainer=$(tamarin_db get maintainer "${maintainer}") echo "$maintainer" } function next_version { commit="$1" # upstream version is given by most recent of release or pkg tag previous_pkg="$(git describe --long --match='pkg/*' $commit 2>/dev/null)" previous_release="$(git describe --long --match='release/*' $commit 2>/dev/null)" if [ -n "$previous_release" ] && [ -n "$previous_pkg" ] then distance_from_pkg=$(get_distance_from_tag "$previous_pkg" "$commit") distance_from_release=$(get_distance_from_tag "$previous_release" "$commit") if [ $distance_from_release -le $distance_from_pkg ] then distance=$distance_from_release version="$(get_upstream_version_from_tag $previous_release)-1" else distance=$distance_from_pkg version="$(get_upstream_version_from_tag $previous_pkg)-$(expr $(get_package_version_from_tag $previous_pkg) + 1)" fi elif [ -n "$previous_release" ] then distance_from_release=$(get_distance_from_tag "$previous_release" "$commit") distance=$distance_from_release version="$(get_upstream_version_from_tag $previous_release)-1" elif [ -n "$previous_pkg" ] then distance=$distance_from_pkg version="$(get_upstream_version_from_tag $previous_pkg)-$(expr $(get_package_version_from_tag $previous_pkg) + 1)" else distance=$(git rev-list --no-merges --count ${commit}..${first_commit}) version="0.0.0-1" fi if [ "$package_level" = 'dev' ] || [ "$package_level" = 'staging' ] then version="${version}~${package_level}+${distance}" fi echo $version } function gen_changelog_entry { ceiling_commit=$1 floor_commit="$(next_step "${ceiling_commit}")" if [ "$(get_hash ${ceiling_commit})" = "$(get_hash ${floor_commit})" ] then return 1 fi if on_pkg_tag $ceiling_commit then ceiling_commit="$(get_previous_pkg_tag $ceiling_commit)" version="$(get_upstream_version_from_tag $ceiling_commit)-$(get_package_version_from_tag $ceiling_commit)" distribution="$(get_distribution_from_tag $ceiling_commit)" else tamarin_info "current commit $ceiling_commit" version=$(next_version $ceiling_commit) distribution="UNRELEASED" fi #current_release="$(git describe --abbrev=0 --always --match='release/*' $ceiling_commit)" tamarin_info "Création de l’entrée de changelog entre ${ceiling_commit} et ${floor_commit}" maintainer="$(packager_from_commit ${ceiling_commit})" package_date="$(date_from_commit ${ceiling_commit})" version=${version/_/-} changelog_entry="${project_name} (${version}) ${distribution}; urgency=${urgency}" echo "$changelog_entry" >> debian/changelog echo >> debian/changelog for commit in $(git log --no-merges --format='%H' ${floor_commit}..${ceiling_commit}) do subject="$(git log -n1 --format=%s ${commit})" echo " * ${subject}" >> debian/changelog #ceiling_commit="$(git log -n1 --format='%H' ${commit}^1)" done echo >> debian/changelog changelog_sign=" -- ${maintainer} ${package_date}" echo "$changelog_sign" >> debian/changelog echo >> debian/changelog ceiling_commit=${floor_commit} } function gen_changelog() { while gen_changelog_entry $ceiling_commit do echo $changelog_entry done } gen_changelog cp debian/changelog /dist/changelog