Control: tags -1 -moreinfo

On Saturday 15 April 2017 01:24 AM, Niels Thykier wrote:
> Sorry for the delay in getting back to you.

Thanks for the detailed review.

> 
>  * In the postrm (RC bug):
> 
> """
> su ${gitlab_user} -c 'psql gitlab_production -c ""' && \
>    su postgres -c "dropdb gitlab_production"
> """
> 
> This does not appear to be idempotent.  If the database is dropped but a
> later part of the purge fails, then this line will prevent dpkg from
> rerunning the purge and reach the desired state (as the code is run
> under "set -e")
> 
> You probably want something like:
> 
> """
>   if su ${gitlab_user} -c 'psql gitlab_production -c ""'; then
>      su postgres -c "dropdb gitlab_production"
>   fi
> """

done

> A similar remark can be made for the following code where it would be
> prudent to apply the same fix:
> 
> """
>         test -e ${gitlab_log_dir} && rm -rf ${gitlab_log_dir}
>         test -e ${gitlab_cache_path} && rm -rf ${gitlab_cache_path}
>         test -e ${gitlab_pid_path} && rm -rf ${gitlab_pid_path}
>         test -e ${gitlab_data_dir} && rm -rf ${gitlab_data_dir}
>         [...]
>       id -u ${gitlab_user} && userdel -r ${gitlab_user}
> 
>     [...]
>     test -f ${nginx_site} && echo "Found nginx site...."
>     [...]
>     # remove the configuration file itself
>     test -f ${nginx_site} && rm -f ${nginx_site}
>     test -f ${gitlab_debian_conf} && rm -f ${gitlab_debian_conf}
>     test -f ${gitlab_yml} && rm -f ${gitlab_yml}
>     test -f ${gitlab_tmpfiles} && rm -f ${gitlab_tmpfiles}
>     test -f ${gitlab_shell_config} && rm -f ${gitlab_shell_config}
>       [...]
>       test -n "${nginx_site}" && ucf --purge ${nginx_site}
>       test -n "${gitlab_debian_conf}" && ucf --purge ${gitlab_debian_conf}
>       test -n "${gitlab_yml}" && ucf --purge ${gitlab_yml}
>       test -n "${gitlab_tmpfiles}" && ucf --purge ${gitlab_tmpfiles}
>       test -n "${gitlab_shell_config}" && ucf -purge ${gitlab_shell_config}
>       [...]
>       test -n "${nginx_site}" && ucfr --purge gitlab ${nginx_site}
>       test -n "${gitlab_debian_conf}" && ucfr --purge gitlab
> ${gitlab_debian_conf}
>       test -n "${gitlab_yml}" && ucfr --purge gitlab ${gitlab_yml}
>       test -n "${gitlab_tmpfiles}" && ucfr --purge gitlab ${gitlab_tmpfiles}
>       test -n "${gitlab_shell_config}" && ucfr -purge gitlab
> ${gitlab_shell_config}
> 
> """

This also done.

> Note I got a follow up remark for the "id+userdel" line below.  As for
> the "test -n", these mean that the script will fail if these values are
> not (still) present in the config OR worse - if the gitlab config is
> already deleted (this is also listed a separate item below)
> 

Changed to if; then;fi like above.

> 
>  * debian/postrm (RC bug):
> 
> The postrm will fail if the admin removes the gitlab config files prior
> to purging gitlab.  This happens because then most of the variables are
> set and as shown above, this will make several test statements evaluate
> to false on the left-hand-side of an && under "set -e".
> 
> Admittedly, this is partly mitigated by gitlab providing its own default
> as a copy under /var/lib/gitlab/gitlab-debian.defaults.  But in theory,
> the machine could fail after removing
> "/var/lib/gitlab/gitlab-debian.defaults" but prior to dpkg committing
> that it had purged gitlab.
> 
> It is an unlikely corner-case, but as it leaves the admin with an
> unpurgeable package it is RC.  To my knowledge, it is *not* sufficient
> to make the removal of the /var/lib file the last thing.  That just
> narrows the window for the issue without fixing it.

Now all conditions are inside if; then; fi blocks so it will ot fail if
file is removed already. If the variables are not defined, it won't try
deletion.

>  * debian/postrm (important)
> 
> As I recall, the general consensus on handling of system users is that
> we should lock them rather than remove them.  The gitlab postrm deletes
> the user:
> 
> """
>       id -u ${gitlab_user} && userdel -r ${gitlab_user}
> """
> 
> That said, I believe gitlab is not the only package deleting the user,
> so it is not RC.

I have kept it like before for now.

>  * debian/config (important/RC bug):
> 
> The config file uses the debconf database as a registry.  It should
> "pre-seed" itself with the defaults from the configuration files.  See
> "man 8 debconf-devel" under "config file handling":
> 
> https://manpages.debian.org/jessie/debconf-doc/debconf-devel.7.en.html#ADVANCED_PROGRAMMING_WITH_DEBCONF
> 

all variables are now seeded from config file.

>  * debian/postinst (RC bug):
> 
> """
>       # Override User for systemd services
>       for service in mailroom unicorn sidekiq workhorse; do
>         path=/etc/systemd/system/gitlab-${service}.service.d
>         mkdir -p $path
>         printf "[Service]\nUser=${gitlab_user}\n" > $path/override.conf
>       done
> """
> 
> This part appears to override
> "/etc/systemd/system/gitlab-${service}.service.d/override.conf"
> completely, disregarding an existing file the admin may have created.
> AFAICT, this happens on "configure" (i.e. it will also apply to
> upgrades) - but even if it only happened on first install, it would
> break admins who use puppet to push out a config file before installing
> gitlab.

Now it checks if the file already exist before writing it.

> There is a similar snippet in the postrm, but it occurs only on purge,
> so that should be fine.
> 
>  * debian/postinst (minor <-> RC bug, not sure):
> 
> If the postinst script is rerun with a new gitlab user, then the
> references in "${gitlab_debian_conf_private}" and
> "${gitlab_yml_private}" is not updated.  I suspect we are in the "RC
> Bug" level because that means the postinst will use the wrong user when
> using ucf to compare the "${gitlab_yml_private}" config with the actual
> config.

Now private copies are also updated.

>  * debian/{postinst,postrm} (possible RC bug):
> 
> I am not entirely confident that the handling of gitlab user is sound in
> case the admin uses a non-standard gitlab user and removes the config
> file prior to purging.  AFAICT, it will cause the postrm to attempt to
> remove the "gitlab" user (which is the default name) rather than the
> actual user.

No, gitlab user is only defined in the config file (it is not in defaults).

>   Even if the postrm would gracefully handle that the default user does
> not exist, then we still leave the system with an open system account
> that should have been locked/deleted.

I don't think we can do anything about an admin removing a config file
and still expecting everything to work.

> I wish I could say I had a proper solution for that, but I don't.  I am
> really not sure how to handle that gracefully AND correctly at the same
> time.  Worst case, the best/only option may be to undo making the gitlab
> user name customizable.  At the very least, it is a lot more complex
> than we initially thought.

Since this is a user facing option (it becomes part of the ssh url git@
or gitlab@), I'd like to keep it selectable.

>  * debian/README.Debian (minor):
> 
> This file uses "export $(cat /etc/gitlab/gitlab-debian.conf)" in at
> least 4 places, which will fail if there are comments in the config
> file.  It would be nice if those were fixed to source the file instead
> like the maintainer scripts does.

Updated.
> 
> 
> I must admit, I am not entirely confident that I found all the possible
> issues in the maintainer scripts.  I would highly recommend a review
> from another person once the above have been fixed.

ok.

In addition to the changes mentioned above, it also fixes the rc bug #858725
diff -Nru gitlab-8.13.11+dfsg/debian/changelog 
gitlab-8.13.11+dfsg1/debian/changelog
--- gitlab-8.13.11+dfsg/debian/changelog        2017-03-23 17:16:50.000000000 
+0530
+++ gitlab-8.13.11+dfsg1/debian/changelog       2017-04-20 11:47:49.000000000 
+0530
@@ -1,3 +1,20 @@
+gitlab (8.13.11+dfsg1-1) unstable; urgency=medium
+
+  [ Balasankar C ]
+  * Repack source to remove fuzzaldrin-plus.js (Closes: #858725)
+
+  [ Pirate Praveen ]
+  * debian/postrm: Make checks idempotent (use if in place of &&)
+  * debian/postrm: Check variables are defined before using them
+  * debian/config: pre-seed variables to debconf db from config files
+  * debian/postinst:
+     - make sure all required variables are present in the config file
+     - handle reconfiguration correctly by reapplying variables from debconf db
+       to config files
+     - Don't touch systemd override.conf if already exist
+
+ -- Pirate Praveen <prav...@debian.org>  Thu, 20 Apr 2017 11:47:49 +0530
+
 gitlab (8.13.11+dfsg-8) unstable; urgency=medium
 
   * Don't fail if gitlab-debian.defaults not found (to support upgrading
diff -Nru gitlab-8.13.11+dfsg/debian/conf/gitlab-debian.conf.example 
gitlab-8.13.11+dfsg1/debian/conf/gitlab-debian.conf.example
--- gitlab-8.13.11+dfsg/debian/conf/gitlab-debian.conf.example  2017-03-23 
17:16:50.000000000 +0530
+++ gitlab-8.13.11+dfsg1/debian/conf/gitlab-debian.conf.example 2017-04-19 
15:11:34.000000000 +0530
@@ -1,3 +1,5 @@
+# Variables with all small letters are debian specific
+# Variables with all caps are passed to gitlab app
 RAILS_ENV=production
 DB=postgres
 gitlab_app_root=/usr/share/gitlab
diff -Nru gitlab-8.13.11+dfsg/debian/conf/gitlab.yml.example 
gitlab-8.13.11+dfsg1/debian/conf/gitlab.yml.example
--- gitlab-8.13.11+dfsg/debian/conf/gitlab.yml.example  2017-03-23 
17:16:50.000000000 +0530
+++ gitlab-8.13.11+dfsg1/debian/conf/gitlab.yml.example 2017-04-19 
15:20:20.000000000 +0530
@@ -46,7 +46,7 @@
     # relative_url_root: /gitlab
 
     # Uncomment and customize if you can't use the default user to run GitLab 
(default: 'git')
-    user: GITLAB_USER
+    user: GITLAB_USER #gitlab_user (DON'T REMOVE THIS COMMENT)
     user_home: /var/lib/gitlab
 
     ## Date & Time settings
diff -Nru gitlab-8.13.11+dfsg/debian/config gitlab-8.13.11+dfsg1/debian/config
--- gitlab-8.13.11+dfsg/debian/config   2017-03-23 17:16:50.000000000 +0530
+++ gitlab-8.13.11+dfsg1/debian/config  2017-04-20 08:41:52.000000000 +0530
@@ -1,11 +1,25 @@
 #!/bin/sh
 # config maintainer script for gitlab
+
+CONFIGFILE=/etc/gitlab/gitlab-debian.conf
  
 set -e
 
 # source debconf stuffs
 . /usr/share/debconf/confmodule
 
+# Load config file, if it exists.
+  if [ -e $CONFIGFILE ]; then
+      . $CONFIGFILE || true
+
+      # Store values from config file into
+      # debconf db.
+      db_set gitlab/fqdn "$GITLAB_HOST"
+      db_set gitlab/user "$gitlab_user"
+      db_set gitlab/ssl "${GITLAB_HTTPS:-false}"
+      db_set gitlab/letsencrypt "${gitlab_letsencrypt:-false}"
+  fi
+
 # What is your fqdn?
 db_input high gitlab/fqdn || true
 db_go
diff -Nru gitlab-8.13.11+dfsg/debian/copyright 
gitlab-8.13.11+dfsg1/debian/copyright
--- gitlab-8.13.11+dfsg/debian/copyright        2017-03-23 17:16:50.000000000 
+0530
+++ gitlab-8.13.11+dfsg1/debian/copyright       2017-04-17 09:36:08.000000000 
+0530
@@ -3,6 +3,7 @@
 Source: https://gitlab.com/gitlab-org/gitlab-ce
 Files-Excluded:
     vendor/assets/javascripts/clipboard.js
+    vendor/assets/javascripts/fuzzaldrin-plus.js
     vendor/assets/javascripts/jquery.cookie.js
     vendor/assets/javascripts/vue-resource.min.js
     vendor/assets/javascripts/vue.min.js
diff -Nru gitlab-8.13.11+dfsg/debian/postinst 
gitlab-8.13.11+dfsg1/debian/postinst
--- gitlab-8.13.11+dfsg/debian/postinst 2017-03-23 17:16:50.000000000 +0530
+++ gitlab-8.13.11+dfsg1/debian/postinst        2017-04-20 11:47:49.000000000 
+0530
@@ -138,77 +138,121 @@
     cd ${gitlab_app_root}
 
     # Obtain hostname from debconf db
+    echo "Configuring hostname and email..."
     db_get gitlab/fqdn
-    if [ "${RET}" != "" ]; then
-      if ! grep GITLAB_HOST ${gitlab_debian_conf_private}; then
-        echo "Configuring hostname and email..."
-        export GITLAB_HOST=${RET} # We need this to configure nginx below
-       cat <<EOF >> ${gitlab_debian_conf_private}
-GITLAB_HOST=${RET} 
-GITLAB_EMAIL_FROM="no-reply@${RET}"
-GITLAB_EMAIL_DISPLAY_NAME="Gitlab"
-GITLAB_EMAIL_REPLY_TO="no-reply@${RET}"
-EOF
-      fi
-
-      # Check if ssl option is selected
-      db_get gitlab/ssl
-      gl_proto="http"
-
-      # Copy example configurations
-      test -f ${gitlab_yml_private} || \
-      cp ${gitlab_yml_example} ${gitlab_yml_private}
-      test -f ${gitlab_shell_config_private} || \
-      cp ${gitlab_shell_config_example} ${gitlab_shell_config_private}
-
-      sed -i "s/GITLAB_USER/${gitlab_user}/" ${gitlab_yml_private}
-
-      if [ "${RET}" = "true" ]; then
-        echo "Configuring nginx with HTTPS..."
-        if ! grep GITLAB_HTTPS ${gitlab_debian_conf_private}; then
-         echo GITLAB_HTTPS=${RET} >> ${gitlab_debian_conf_private}
-         # Workaround for #813770
-         gl_proto="https"
-         echo "Configuring gitlab with HTTPS..."
-         sed -i "s/#port: 80/port: 443/" ${gitlab_yml_private}
-         sed -i "s/https: false/https: true/" ${gitlab_yml_private}
-          echo "Updating gitlab_url in gitlab-shell configuration..."
-          sed -i \
+    GITLAB_HOST=$RET
+    GITLAB_EMAIL_FROM="no-reply@$GITLAB_HOST"
+    GITLAB_EMAIL_DISPLAY_NAME="Gitlab"
+    GITLAB_EMAIL_REPLY_TO="no-reply@$GITLAB_HOST"
+    db_get gitlab/user
+    gitlab_user=$RET
+    # Check if ssl option is selected
+    db_get gitlab/ssl
+    GITLAB_HTTPS=$RET
+    gl_proto="http"
+    db_get gitlab/letsencrypt
+    gitlab_letsencrypt=$RET
+
+    cp -a -f ${gitlab_debian_conf_private} ${gitlab_debian_conf_private}.tmp
+
+    # If the admin deleted or commented some variables but then set
+    # them via debconf, (re-)add them to the conffile.
+    test -z "$GITLAB_HOST" || grep -Eq '^ *GITLAB_HOST=' 
${gitlab_debian_conf_private} || \
+        echo "GITLAB_HOST=" >> ${gitlab_debian_conf_private}
+    test -z "$GITLAB_EMAIL_FROM" || grep -Eq '^ *GITLAB_EMAIL_FROM=' 
${gitlab_debian_conf_private} || \
+        echo "GITLAB_EMAIL_FROM=" >> ${gitlab_debian_conf_private}
+    test -z "$GITLAB_EMAIL_DISPLAY_NAME" || grep -Eq '^ 
*GITLAB_EMAIL_DISPLAY_NAME=' ${gitlab_debian_conf_private} || \
+        echo "GITLAB_EMAIL_DISPLAY_NAME=" >> ${gitlab_debian_conf_private}
+    test -z "$GITLAB_EMAIL_REPLY_TO" || grep -Eq '^ *GITLAB_EMAIL_REPLY_TO=' 
${gitlab_debian_conf_private} || \
+        echo "GITLAB_EMAIL_REPLY_TO=" >> ${gitlab_debian_conf_private}
+    test -z "$gitlab_user" || grep -Eq '^ *gitlab_user=' 
${gitlab_debian_conf_private} || \
+        echo "gitlab_user=" >> ${gitlab_debian_conf_private}
+    test -z "$GITLAB_HTTPS" || grep -Eq '^ *GITLAB_HTTPS=' 
${gitlab_debian_conf_private} || \
+        echo "GITLAB_HTTPS=" >> ${gitlab_debian_conf_private}
+    test -z "$gitlab_letsencrypt" || grep -Eq '^ *gitlab_letsencrypt=' 
${gitlab_debian_conf_private} || \
+        echo "gitlab_letsencrypt=" >> ${gitlab_debian_conf_private}
+    sed -e "s/^ *GITLAB_HOST=.*/GITLAB_HOST=\"$GITLAB_HOST\"/" \
+        -e "s/^ 
*GITLAB_EMAIL_FROM=.*/GITLAB_EMAIL_FROM=\"$GITLAB_EMAIL_FROM\"/" \
+        -e "s/^ 
*GITLAB_EMAIL_DISPLAY_NAME=.*/GITLAB_EMAIL_DISPLAY_NAME=\"$GITLAB_EMAIL_DISPLAY_NAME\"/"
 \
+        -e "s/^ 
*GITLAB_EMAIL_REPLY_TO=.*/GITLAB_EMAIL_REPLY_TO=\"$GITLAB_EMAIL_REPLY_TO\"/" \
+        -e "s/^ *gitlab_user=.*/gitlab_user=\"$gitlab_user\"/" \
+        -e "s/^ *GITLAB_HTTPS=.*/GITLAB_HTTPS=\"$GITLAB_HTTPS\"/" \
+        -e "s/^ 
*gitlab_letsencrypt=.*/gitlab_letsencrypt=\"$gitlab_letsencrypt\"/" \
+            < ${gitlab_debian_conf_private} > ${gitlab_debian_conf_private}.tmp
+        mv -f ${gitlab_debian_conf_private}.tmp ${gitlab_debian_conf_private}
+
+    # Copy example configurations
+    test -f ${gitlab_yml_private} || \
+    cp ${gitlab_yml_example} ${gitlab_yml_private}
+    test -f ${gitlab_shell_config_private} || \
+    cp ${gitlab_shell_config_example} ${gitlab_shell_config_private}
+
+    # Set gitlab user first time
+    sed -i "s/GITLAB_USER/${gitlab_user}/" ${gitlab_yml_private}
+    # Update gitlab user (its a hack, proper fix is to have gitlab accept 
GITLAB_USER variable)
+    sed -i "s/^ *user:.* #gitlab_user/    user: $gitlab_user #gitlab_user/" 
${gitlab_yml_private}
+
+    if [ "$GITLAB_HTTPS" = "true" ]; then
+      echo "Configuring nginx with HTTPS..."
+      # Workaround for #813770
+      gl_proto="https"
+      echo "Configuring gitlab with HTTPS..."
+      sed -i "s/#port: 80/port: 443/" ${gitlab_yml_private}
+      sed -i "s/https: false/https: true/" ${gitlab_yml_private}
+      echo "Updating gitlab_url in gitlab-shell configuration..."
+      sed -i \
          "s/gitlab_url: http*:\/\/.*/gitlab_url: 
${gl_proto}:\/\/${GITLAB_HOST}/"\
          ${gitlab_shell_config_private}
+      
+      mkdir -p /etc/gitlab/ssl
+      nginx_conf_example=${nginx_ssl_conf_example}
 
-       fi
-        
-        mkdir -p /etc/gitlab/ssl
-        nginx_conf_example=${nginx_ssl_conf_example}
-
-        # Check if letsencrypt option is selected
-        db_get gitlab/letsencrypt
-        if [ "${RET}" = "true" ]; then
+      # Check if letsencrypt option is selected
+      if [ "$gitlab_letsencrypt" = "true" ]; then
          echo "Configuring letsencrypt..."
-          ln -sf /etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem \
-          /etc/gitlab/ssl/gitlab.crt
-          ln -sf /etc/letsencrypt/live/${GITLAB_HOST}/privkey.pem \
-          /etc/gitlab/ssl/gitlab.key
+        ln -sf /etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem \
+        /etc/gitlab/ssl/gitlab.crt
+        ln -sf /etc/letsencrypt/live/${GITLAB_HOST}/privkey.pem \
+        /etc/gitlab/ssl/gitlab.key
            
-         # Check if certificate is already present
-         if [ -e /etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem ]; then
-           echo "Let's encrypt certificate already present."
-         else
-           # Port 80 and 443 should be available for letsencrypt
-           if command -v nginx > /dev/null; then
-             echo "Stopping nginx for letsencrypt..."
-             invoke-rc.d nginx stop
-           fi
+        # Check if certificate is already present
+        if [ -e /etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem ]; then
+          echo "Let's encrypt certificate already present."
+        else
+          # Port 80 and 443 should be available for letsencrypt
+          if command -v nginx > /dev/null; then
+           echo "Stopping nginx for letsencrypt..."
+           invoke-rc.d nginx stop
+         fi
 
-           letsencrypt -d ${GITLAB_HOST} certonly || {
+         letsencrypt --standalone -d ${GITLAB_HOST} certonly || {
            echo "letsencrypt auto configuration failed..."
            echo "Stop your webserver and try running letsencrypt manually..."
            echo "letsencrypt -d ${GITLAB_HOST} certonly" 
-           }
-         fi
-        fi
+         }
+        fi 
       fi
+    else
+      # Revert https setting
+      sed -i "s/port: 443/#port: 80/" ${gitlab_yml_private}
+      sed -i "s/https: true/https: false/" ${gitlab_yml_private}
+    fi
+
+    # Cleanup in case letsencrypt were disabled later
+    if [ "$gitlab_letsencrypt" = "false" ]; then
+        if [ -L /etc/gitlab/ssl/gitlab.crt ]; then
+          if [ "$(file /etc/gitlab/ssl/gitlab.crt|awk '{ print $NF }')" = 
"/etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem" ]; then
+            echo "Removing symbolic links to letsencrypt certificate..."
+            rm -f /etc/gitlab/ssl/gitlab.crt
+          fi
+        fi
+        if [ -L /etc/gitlab/ssl/gitlab.key ]; then
+          if [ "$(file /etc/gitlab/ssl/gitlab.key|awk '{ print $NF }')" = 
"/etc/letsencrypt/live/${GITLAB_HOST}/privkey.pem" ]; then
+            echo "Removing symbolic links to letsencrypt certificate private 
key..."
+            rm -f /etc/gitlab/ssl/gitlab.key
+          fi
+        fi
+    fi
 
       # Manage tmpfiles.d/gitlab.conf via ucf
       test -f ${gitlab_tmpfiles_private} || \
@@ -222,7 +266,13 @@
       for service in mailroom unicorn sidekiq workhorse; do
         path=/etc/systemd/system/gitlab-${service}.service.d
         mkdir -p $path
-        printf "[Service]\nUser=${gitlab_user}\n" > $path/override.conf
+        if [ -e $path/override.conf ]; then
+          echo "$path/override.conf already exist"
+          # Make sure only gitlab user is updated
+          sed -i "s/^ *User=.*/User=$gitlab_user/" $path/override.conf
+        else
+          printf "[Service]\nUser=${gitlab_user}\n" > $path/override.conf
+        fi
       done
 
       # Manage gitlab-shell's config.yml via ucf
@@ -250,7 +300,6 @@
           ucf --debconf-ok --three-way ${nginx_site_private} ${nginx_site}
           ucfr gitlab ${nginx_site}
           ln -fs ${nginx_site} /etc/nginx/sites-enabled/
-          rm -f ${nginx_conf_example_tmp}
         else
           echo "nginx example configuration file not found"
           exit 1
@@ -261,10 +310,6 @@
         echo "Reloading nginx configuration..."
         invoke-rc.d nginx reload
       fi
-    else
-      echo "Failed to retrieve fully qualified domain name"
-      exit 1
-    fi
     db_stop
 
     echo "Create database if not present"
diff -Nru gitlab-8.13.11+dfsg/debian/postrm gitlab-8.13.11+dfsg1/debian/postrm
--- gitlab-8.13.11+dfsg/debian/postrm   2017-03-23 17:16:50.000000000 +0530
+++ gitlab-8.13.11+dfsg1/debian/postrm  2017-04-17 14:38:24.000000000 +0530
@@ -18,8 +18,18 @@
 # Ensure the menu system is updated
 
 # Read debian specific configuration
-test -f ${gitlab_debian_conf} && . ${gitlab_debian_conf}
-test -f ${gitlab_debian_defaults} && . ${gitlab_debian_defaults}
+if [ -f ${gitlab_debian_conf} ]; then . ${gitlab_debian_conf}; fi
+if [ -f ${gitlab_debian_defaults} ]; then . ${gitlab_debian_defaults}; fi
+
+safely_remove() {
+  CANDIDATE_DIR=$1
+  if [ -n ${CANDIDATE_DIR} ];then
+    if [ -e ${CANDIDATE_DIR} ]; then
+      echo "Removing $i..."
+      rm -rf ${CANDIDATE_DIR}
+    fi
+  fi
+}
 
 case "$1" in
   remove)
@@ -50,27 +60,27 @@
       if [ "${RET}" = "true" ]; then
         if [ -d ${gitlab_data_dir} ]; then
           for i in shared public db repositories secrets.yml Gemfile.lock; do
-            test -e ${gitlab_data_dir}/$i && rm -rf ${gitlab_data_dir}/$i
+            if [ -e ${gitlab_data_dir}/$i ]; then rm -rf 
${gitlab_data_dir}/$i; fi
           done
         fi
-        test -e ${gitlab_log_dir} && rm -rf ${gitlab_log_dir}
-        test -e ${gitlab_cache_path} && rm -rf ${gitlab_cache_path}
-        test -e ${gitlab_pid_path} && rm -rf ${gitlab_pid_path}
-        test -e ${gitlab_data_dir} && rm -rf ${gitlab_data_dir}
+       for i in ${gitlab_log_dir} ${gitlab_cache_path} ${gitlab_pid_path} \
+${gitlab_data_dir}; do
+               safely_remove $i
+       done
         if [ ! -z "${gitlab_user}" ]; then
             # Do only if gitlab_user is set
             if command -v dropdb >/dev/null; then
                 echo "Removing Database: gitlab_production"
-                su ${gitlab_user} -c 'psql gitlab_production -c ""' && su 
postgres -c "dropdb gitlab_production"
+                if su ${gitlab_user} -c 'psql gitlab_production -c ""' ; then 
su postgres -c "dropdb gitlab_production"; fi
             else
                 echo "dropdb command not found. Hence not removing database."
            fi
            echo "Removing user: ${gitlab_user}"
-           id -u ${gitlab_user} && userdel -r ${gitlab_user}
+           if id -u ${gitlab_user}; then userdel -r ${gitlab_user}; fi
         else
             echo "gitlab_user not set. Hence not removing user."
         fi
-        rm -rf ${gitlab_ssl_path}
+        safely_remove ${gitlab_ssl_path}
       fi
 
       # Remove my changes to the db.
@@ -79,7 +89,7 @@
 
     nginx_site="/etc/nginx/sites-available/${GITLAB_HOST}"
 
-    test -f ${nginx_site} && echo "Found nginx site configuration at 
${nginx_site}..."
+    if [ -f ${nginx_site} ]; then echo "Found nginx site configuration at 
${nginx_site}..."; fi
 
 
     # we mimic dpkg as closely as possible, so we remove configuration
@@ -93,32 +103,21 @@
        rm -f ${gitlab_shell_config}$ext
     done
  
-    # remove the configuration file itself
-    test -f ${nginx_site} && rm -f ${nginx_site}
-    test -f ${gitlab_debian_conf} && rm -f ${gitlab_debian_conf}
-    test -f ${gitlab_yml} && rm -f ${gitlab_yml}
-    test -f ${gitlab_tmpfiles} && rm -f ${gitlab_tmpfiles}
-    test -f ${gitlab_shell_config} && rm -f ${gitlab_shell_config}
-
-    # and finally clear it out from the ucf database
-    if which ucf >/dev/null; then
-      test -n "${nginx_site}" && ucf --purge ${nginx_site}
-      test -n "${gitlab_debian_conf}" && ucf --purge ${gitlab_debian_conf}
-      test -n "${gitlab_yml}" && ucf --purge ${gitlab_yml}
-      test -n "${gitlab_tmpfiles}" && ucf --purge ${gitlab_tmpfiles}
-      test -n "${gitlab_shell_config}" && ucf -purge ${gitlab_shell_config}    
    
-    fi
-    
-    if which ucfr >/dev/null; then
-      test -n "${nginx_site}" && ucfr --purge gitlab ${nginx_site}
-      test -n "${gitlab_debian_conf}" && ucfr --purge gitlab 
${gitlab_debian_conf}
-      test -n "${gitlab_yml}" && ucfr --purge gitlab ${gitlab_yml}
-      test -n "${gitlab_tmpfiles}" && ucfr --purge gitlab ${gitlab_tmpfiles}
-      test -n "${gitlab_shell_config}" && ucfr -purge gitlab 
${gitlab_shell_config}
-    fi
+    for i in ${nginx_site} ${gitlab_debian_conf} ${gitlab_yml} \
+${gitlab_tmpfiles} ${gitlab_shell_config}; do
+      # remove the configuration file itself
+        safely_remove $i
+      # and finally clear it out from the ucf database
+      if which ucf >/dev/null; then
+        if [ -n "$i" ]; then ucf --purge $i; fi
+      fi
+      if which ucfr >/dev/null; then
+        if [ -n "$i" ]; then ucfr --purge gitlab $i; fi
+      fi
+    done
 
     # remove generated assets
-    rm -rf ${gitlab_data_dir}/public/assets
+    if [ -n ${gitlab_data_dir} ]; then safely_remove 
${gitlab_data_dir}/public/assets; fi
       
     # Remove private copies of configuration files
     rm -f ${nginx_site_private}
diff -Nru gitlab-8.13.11+dfsg/debian/README.Debian 
gitlab-8.13.11+dfsg1/debian/README.Debian
--- gitlab-8.13.11+dfsg/debian/README.Debian    2017-03-23 17:16:50.000000000 
+0530
+++ gitlab-8.13.11+dfsg1/debian/README.Debian   2017-04-20 11:47:49.000000000 
+0530
@@ -64,7 +64,7 @@
 directory /usr/share/gitlab and with the environment variables from
 /etc/gitlab/gitlab-debian.conf set. So above command could be run like:
 
-    $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && export $(cat 
/etc/gitlab/gitlab-debian.conf) && rake XXX RAILS_ENV=production'
+    $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && . 
/etc/gitlab/gitlab-debian.conf && export DB RAILS_ENV && rake XXX 
RAILS_ENV=production'
 
 One useful command to run in this environment is:
 
@@ -120,19 +120,19 @@
       $ find /var/lib/gitlab/public/uploads -type f -exec chmod 0644 {} \;
       $ find /var/lib/gitlab/public/uploads -type d -not -path 
/var/lib/gitlab/public/uploads -exec chmod 0700 {} \;
  10. Migrate the database:
-      $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && export $(cat 
/etc/gitlab/gitlab-debian.conf) && rake db:migrate RAILS_ENV=production'
+      $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && . 
/etc/gitlab/gitlab-debian.conf && export DB RAILS_ENV && rake db:migrate 
RAILS_ENV=production'
  11. Fix hooks:
       # su gitlab
       $ /usr/share/gitlab-shell/bin/create-hooks
  12. Start gitlab:
        $ systemctl start gitlab.service
  13. Check the installation:
-      $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && export $(cat 
/etc/gitlab/gitlab-debian.conf) && rake gitlab:check RAILS_ENV=production'
+      $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && . 
/etc/gitlab/gitlab-debian.conf && export DB RAILS_ENV && rake gitlab:check 
RAILS_ENV=production'
 
 Resetting admin password without web interface
 ==============================================
 
-    $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && export $(cat 
/etc/gitlab/gitlab-debian.conf) && rails console production'
+    $ runuser -u gitlab -- sh -c 'cd /usr/share/gitlab && . 
/etc/gitlab/gitlab-debian.conf && export DB RAILS_ENV && rails console 
production'
     irb(main):001:0> user = User.where(admin: true).first
     irb(main):002:0> user.password = 'secret_pass'
     irb(main):003:0> user.password_confirmation = 'secret_pass'
diff -Nru gitlab-8.13.11+dfsg/vendor/assets/javascripts/fuzzaldrin-plus.js 
gitlab-8.13.11+dfsg1/vendor/assets/javascripts/fuzzaldrin-plus.js
--- gitlab-8.13.11+dfsg/vendor/assets/javascripts/fuzzaldrin-plus.js    
2017-01-10 22:23:38.000000000 +0530
+++ gitlab-8.13.11+dfsg1/vendor/assets/javascripts/fuzzaldrin-plus.js   
1970-01-01 05:30:00.000000000 +0530
@@ -1,1161 +0,0 @@
-/*!
- * fuzzaldrin-plus.js - 0.3.1
- * https://github.com/jeancroy/fuzzaldrin-plus
- *
- * Copyright 2016 - Jean Christophe Roy
- * Released under the MIT license
- * https://github.com/jeancroy/fuzzaldrin-plus/raw/master/LICENSE.md
- */
-(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof 
require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var 
f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var 
l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return 
s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof 
require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return 
s})({1:[function(require,module,exports){
-fuzzaldrinPlus = require('fuzzaldrin-plus');
-
-},{"fuzzaldrin-plus":3}],2:[function(require,module,exports){
-(function() {
-  var PathSeparator, legacy_scorer, pluckCandidates, scorer, sortCandidates;
-
-  scorer = require('./scorer');
-
-  legacy_scorer = require('./legacy');
-
-  pluckCandidates = function(a) {
-    return a.candidate;
-  };
-
-  sortCandidates = function(a, b) {
-    return b.score - a.score;
-  };
-
-  PathSeparator = require('path').sep;
-
-  module.exports = function(candidates, query, _arg) {
-    var allowErrors, bAllowErrors, bKey, candidate, coreQuery, key, legacy, 
maxInners, maxResults, prepQuery, queryHasSlashes, score, scoredCandidates, 
spotLeft, string, _i, _j, _len, _len1, _ref;
-    _ref = _arg != null ? _arg : {}, key = _ref.key, maxResults = 
_ref.maxResults, maxInners = _ref.maxInners, allowErrors = _ref.allowErrors, 
legacy = _ref.legacy;
-    scoredCandidates = [];
-    spotLeft = (maxInners != null) && maxInners > 0 ? maxInners : 
candidates.length;
-    bAllowErrors = !!allowErrors;
-    bKey = key != null;
-    prepQuery = scorer.prepQuery(query);
-    if (!legacy) {
-      for (_i = 0, _len = candidates.length; _i < _len; _i++) {
-        candidate = candidates[_i];
-        string = bKey ? candidate[key] : candidate;
-        if (!string) {
-          continue;
-        }
-        score = scorer.score(string, query, prepQuery, bAllowErrors);
-        if (score > 0) {
-          scoredCandidates.push({
-            candidate: candidate,
-            score: score
-          });
-          if (!--spotLeft) {
-            break;
-          }
-        }
-      }
-    } else {
-      queryHasSlashes = prepQuery.depth > 0;
-      coreQuery = prepQuery.core;
-      for (_j = 0, _len1 = candidates.length; _j < _len1; _j++) {
-        candidate = candidates[_j];
-        string = key != null ? candidate[key] : candidate;
-        if (!string) {
-          continue;
-        }
-        score = legacy_scorer.score(string, coreQuery, queryHasSlashes);
-        if (!queryHasSlashes) {
-          score = legacy_scorer.basenameScore(string, coreQuery, score);
-        }
-        if (score > 0) {
-          scoredCandidates.push({
-            candidate: candidate,
-            score: score
-          });
-        }
-      }
-    }
-    scoredCandidates.sort(sortCandidates);
-    candidates = scoredCandidates.map(pluckCandidates);
-    if (maxResults != null) {
-      candidates = candidates.slice(0, maxResults);
-    }
-    return candidates;
-  };
-
-}).call(this);
-
-},{"./legacy":4,"./scorer":6,"path":7}],3:[function(require,module,exports){
-(function() {
-  var PathSeparator, filter, legacy_scorer, matcher, prepQueryCache, scorer;
-
-  scorer = require('./scorer');
-
-  legacy_scorer = require('./legacy');
-
-  filter = require('./filter');
-
-  matcher = require('./matcher');
-
-  PathSeparator = require('path').sep;
-
-  prepQueryCache = null;
-
-  module.exports = {
-    filter: function(candidates, query, options) {
-      if (!((query != null ? query.length : void 0) && (candidates != null ? 
candidates.length : void 0))) {
-        return [];
-      }
-      return filter(candidates, query, options);
-    },
-    prepQuery: function(query) {
-      return scorer.prepQuery(query);
-    },
-    score: function(string, query, prepQuery, _arg) {
-      var allowErrors, coreQuery, legacy, queryHasSlashes, score, _ref;
-      _ref = _arg != null ? _arg : {}, allowErrors = _ref.allowErrors, legacy 
= _ref.legacy;
-      if (!((string != null ? string.length : void 0) && (query != null ? 
query.length : void 0))) {
-        return 0;
-      }
-      if (prepQuery == null) {
-        prepQuery = prepQueryCache && prepQueryCache.query === query ? 
prepQueryCache : (prepQueryCache = scorer.prepQuery(query));
-      }
-      if (!legacy) {
-        score = scorer.score(string, query, prepQuery, !!allowErrors);
-      } else {
-        queryHasSlashes = prepQuery.depth > 0;
-        coreQuery = prepQuery.core;
-        score = legacy_scorer.score(string, coreQuery, queryHasSlashes);
-        if (!queryHasSlashes) {
-          score = legacy_scorer.basenameScore(string, coreQuery, score);
-        }
-      }
-      return score;
-    },
-    match: function(string, query, prepQuery, _arg) {
-      var allowErrors, baseMatches, matches, query_lw, string_lw, _i, _ref, 
_results;
-      allowErrors = (_arg != null ? _arg : {}).allowErrors;
-      if (!string) {
-        return [];
-      }
-      if (!query) {
-        return [];
-      }
-      if (string === query) {
-        return (function() {
-          _results = [];
-          for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > 
_ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }
-          return _results;
-        }).apply(this);
-      }
-      if (prepQuery == null) {
-        prepQuery = prepQueryCache && prepQueryCache.query === query ? 
prepQueryCache : (prepQueryCache = scorer.prepQuery(query));
-      }
-      if (!(allowErrors || scorer.isMatch(string, prepQuery.core_lw, 
prepQuery.core_up))) {
-        return [];
-      }
-      string_lw = string.toLowerCase();
-      query_lw = prepQuery.query_lw;
-      matches = matcher.match(string, string_lw, prepQuery);
-      if (matches.length === 0) {
-        return matches;
-      }
-      if (string.indexOf(PathSeparator) > -1) {
-        baseMatches = matcher.basenameMatch(string, string_lw, prepQuery);
-        matches = matcher.mergeMatches(matches, baseMatches);
-      }
-      return matches;
-    }
-  };
-
-}).call(this);
-
-},{"./filter":2,"./legacy":4,"./matcher":5,"./scorer":6,"path":7}],4:[function(require,module,exports){
-(function() {
-  var PathSeparator, queryIsLastPathSegment;
-
-  PathSeparator = require('path').sep;
-
-  exports.basenameScore = function(string, query, score) {
-    var base, depth, index, lastCharacter, segmentCount, slashCount;
-    index = string.length - 1;
-    while (string[index] === PathSeparator) {
-      index--;
-    }
-    slashCount = 0;
-    lastCharacter = index;
-    base = null;
-    while (index >= 0) {
-      if (string[index] === PathSeparator) {
-        slashCount++;
-        if (base == null) {
-          base = string.substring(index + 1, lastCharacter + 1);
-        }
-      } else if (index === 0) {
-        if (lastCharacter < string.length - 1) {
-          if (base == null) {
-            base = string.substring(0, lastCharacter + 1);
-          }
-        } else {
-          if (base == null) {
-            base = string;
-          }
-        }
-      }
-      index--;
-    }
-    if (base === string) {
-      score *= 2;
-    } else if (base) {
-      score += exports.score(base, query);
-    }
-    segmentCount = slashCount + 1;
-    depth = Math.max(1, 10 - segmentCount);
-    score *= depth * 0.01;
-    return score;
-  };
-
-  exports.score = function(string, query) {
-    var character, characterScore, indexInQuery, indexInString, 
lowerCaseIndex, minIndex, queryLength, queryScore, stringLength, 
totalCharacterScore, upperCaseIndex, _ref;
-    if (string === query) {
-      return 1;
-    }
-    if (queryIsLastPathSegment(string, query)) {
-      return 1;
-    }
-    totalCharacterScore = 0;
-    queryLength = query.length;
-    stringLength = string.length;
-    indexInQuery = 0;
-    indexInString = 0;
-    while (indexInQuery < queryLength) {
-      character = query[indexInQuery++];
-      lowerCaseIndex = string.indexOf(character.toLowerCase());
-      upperCaseIndex = string.indexOf(character.toUpperCase());
-      minIndex = Math.min(lowerCaseIndex, upperCaseIndex);
-      if (minIndex === -1) {
-        minIndex = Math.max(lowerCaseIndex, upperCaseIndex);
-      }
-      indexInString = minIndex;
-      if (indexInString === -1) {
-        return 0;
-      }
-      characterScore = 0.1;
-      if (string[indexInString] === character) {
-        characterScore += 0.1;
-      }
-      if (indexInString === 0 || string[indexInString - 1] === PathSeparator) {
-        characterScore += 0.8;
-      } else if ((_ref = string[indexInString - 1]) === '-' || _ref === '_' || 
_ref === ' ') {
-        characterScore += 0.7;
-      }
-      string = string.substring(indexInString + 1, stringLength);
-      totalCharacterScore += characterScore;
-    }
-    queryScore = totalCharacterScore / queryLength;
-    return ((queryScore * (queryLength / stringLength)) + queryScore) / 2;
-  };
-
-  queryIsLastPathSegment = function(string, query) {
-    if (string[string.length - query.length - 1] === PathSeparator) {
-      return string.lastIndexOf(query) === string.length - query.length;
-    }
-  };
-
-  exports.match = function(string, query, stringOffset) {
-    var character, indexInQuery, indexInString, lowerCaseIndex, matches, 
minIndex, queryLength, stringLength, upperCaseIndex, _i, _ref, _results;
-    if (stringOffset == null) {
-      stringOffset = 0;
-    }
-    if (string === query) {
-      return (function() {
-        _results = [];
-        for (var _i = stringOffset, _ref = stringOffset + string.length; 
stringOffset <= _ref ? _i < _ref : _i > _ref; stringOffset <= _ref ? _i++ : 
_i--){ _results.push(_i); }
-        return _results;
-      }).apply(this);
-    }
-    queryLength = query.length;
-    stringLength = string.length;
-    indexInQuery = 0;
-    indexInString = 0;
-    matches = [];
-    while (indexInQuery < queryLength) {
-      character = query[indexInQuery++];
-      lowerCaseIndex = string.indexOf(character.toLowerCase());
-      upperCaseIndex = string.indexOf(character.toUpperCase());
-      minIndex = Math.min(lowerCaseIndex, upperCaseIndex);
-      if (minIndex === -1) {
-        minIndex = Math.max(lowerCaseIndex, upperCaseIndex);
-      }
-      indexInString = minIndex;
-      if (indexInString === -1) {
-        return [];
-      }
-      matches.push(stringOffset + indexInString);
-      stringOffset += indexInString + 1;
-      string = string.substring(indexInString + 1, stringLength);
-    }
-    return matches;
-  };
-
-}).call(this);
-
-},{"path":7}],5:[function(require,module,exports){
-(function() {
-  var PathSeparator, scorer;
-
-  PathSeparator = require('path').sep;
-
-  scorer = require('./scorer');
-
-  exports.basenameMatch = function(subject, subject_lw, prepQuery) {
-    var basePos, depth, end;
-    end = subject.length - 1;
-    while (subject[end] === PathSeparator) {
-      end--;
-    }
-    basePos = subject.lastIndexOf(PathSeparator, end);
-    if (basePos === -1) {
-      return [];
-    }
-    depth = prepQuery.depth;
-    while (depth-- > 0) {
-      basePos = subject.lastIndexOf(PathSeparator, basePos - 1);
-      if (basePos === -1) {
-        return [];
-      }
-    }
-    basePos++;
-    end++;
-    return exports.match(subject.slice(basePos, end), 
subject_lw.slice(basePos, end), prepQuery, basePos);
-  };
-
-  exports.mergeMatches = function(a, b) {
-    var ai, bj, i, j, m, n, out;
-    m = a.length;
-    n = b.length;
-    if (n === 0) {
-      return a.slice();
-    }
-    if (m === 0) {
-      return b.slice();
-    }
-    i = -1;
-    j = 0;
-    bj = b[j];
-    out = [];
-    while (++i < m) {
-      ai = a[i];
-      while (bj <= ai && ++j < n) {
-        if (bj < ai) {
-          out.push(bj);
-        }
-        bj = b[j];
-      }
-      out.push(ai);
-    }
-    while (j < n) {
-      out.push(b[j++]);
-    }
-    return out;
-  };
-
-  exports.match = function(subject, subject_lw, prepQuery, offset) {
-    var DIAGONAL, LEFT, STOP, UP, acro_score, align, backtrack, csc_diag, 
csc_row, csc_score, i, j, m, matches, move, n, pos, query, query_lw, score, 
score_diag, score_row, score_up, si_lw, start, trace;
-    if (offset == null) {
-      offset = 0;
-    }
-    query = prepQuery.query;
-    query_lw = prepQuery.query_lw;
-    m = subject.length;
-    n = query.length;
-    acro_score = scorer.scoreAcronyms(subject, subject_lw, query, 
query_lw).score;
-    score_row = new Array(n);
-    csc_row = new Array(n);
-    STOP = 0;
-    UP = 1;
-    LEFT = 2;
-    DIAGONAL = 3;
-    trace = new Array(m * n);
-    pos = -1;
-    j = -1;
-    while (++j < n) {
-      score_row[j] = 0;
-      csc_row[j] = 0;
-    }
-    i = -1;
-    while (++i < m) {
-      score = 0;
-      score_up = 0;
-      csc_diag = 0;
-      si_lw = subject_lw[i];
-      j = -1;
-      while (++j < n) {
-        csc_score = 0;
-        align = 0;
-        score_diag = score_up;
-        if (query_lw[j] === si_lw) {
-          start = scorer.isWordStart(i, subject, subject_lw);
-          csc_score = csc_diag > 0 ? csc_diag : 
scorer.scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start);
-          align = score_diag + scorer.scoreCharacter(i, j, start, acro_score, 
csc_score);
-        }
-        score_up = score_row[j];
-        csc_diag = csc_row[j];
-        if (score > score_up) {
-          move = LEFT;
-        } else {
-          score = score_up;
-          move = UP;
-        }
-        if (align > score) {
-          score = align;
-          move = DIAGONAL;
-        } else {
-          csc_score = 0;
-        }
-        score_row[j] = score;
-        csc_row[j] = csc_score;
-        trace[++pos] = score > 0 ? move : STOP;
-      }
-    }
-    i = m - 1;
-    j = n - 1;
-    pos = i * n + j;
-    backtrack = true;
-    matches = [];
-    while (backtrack && i >= 0 && j >= 0) {
-      switch (trace[pos]) {
-        case UP:
-          i--;
-          pos -= n;
-          break;
-        case LEFT:
-          j--;
-          pos--;
-          break;
-        case DIAGONAL:
-          matches.push(i + offset);
-          j--;
-          i--;
-          pos -= n + 1;
-          break;
-        default:
-          backtrack = false;
-      }
-    }
-    matches.reverse();
-    return matches;
-  };
-
-}).call(this);
-
-},{"./scorer":6,"path":7}],6:[function(require,module,exports){
-(function() {
-  var AcronymResult, PathSeparator, Query, basenameScore, coreChars, countDir, 
doScore, emptyAcronymResult, file_coeff, isMatch, isSeparator, isWordEnd, 
isWordStart, miss_coeff, opt_char_re, pos_bonus, scoreAcronyms, scoreCharacter, 
scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, 
scoreSize, tau_depth, tau_size, truncatedUpperCase, wm;
-
-  PathSeparator = require('path').sep;
-
-  wm = 150;
-
-  pos_bonus = 20;
-
-  tau_depth = 13;
-
-  tau_size = 85;
-
-  file_coeff = 1.2;
-
-  miss_coeff = 0.75;
-
-  opt_char_re = /[ _\-:\/\\]/g;
-
-  exports.coreChars = coreChars = function(query) {
-    return query.replace(opt_char_re, '');
-  };
-
-  exports.score = function(string, query, prepQuery, allowErrors) {
-    var score, string_lw;
-    if (prepQuery == null) {
-      prepQuery = new Query(query);
-    }
-    if (allowErrors == null) {
-      allowErrors = false;
-    }
-    if (!(allowErrors || isMatch(string, prepQuery.core_lw, 
prepQuery.core_up))) {
-      return 0;
-    }
-    string_lw = string.toLowerCase();
-    score = doScore(string, string_lw, prepQuery);
-    return Math.ceil(basenameScore(string, string_lw, prepQuery, score));
-  };
-
-  Query = (function() {
-    function Query(query) {
-      if (!(query != null ? query.length : void 0)) {
-        return null;
-      }
-      this.query = query;
-      this.query_lw = query.toLowerCase();
-      this.core = coreChars(query);
-      this.core_lw = this.core.toLowerCase();
-      this.core_up = truncatedUpperCase(this.core);
-      this.depth = countDir(query, query.length);
-    }
-
-    return Query;
-
-  })();
-
-  exports.prepQuery = function(query) {
-    return new Query(query);
-  };
-
-  exports.isMatch = isMatch = function(subject, query_lw, query_up) {
-    var i, j, m, n, qj_lw, qj_up, si;
-    m = subject.length;
-    n = query_lw.length;
-    if (!m || n > m) {
-      return false;
-    }
-    i = -1;
-    j = -1;
-    while (++j < n) {
-      qj_lw = query_lw[j];
-      qj_up = query_up[j];
-      while (++i < m) {
-        si = subject[i];
-        if (si === qj_lw || si === qj_up) {
-          break;
-        }
-      }
-      if (i === m) {
-        return false;
-      }
-    }
-    return true;
-  };
-
-  doScore = function(subject, subject_lw, prepQuery) {
-    var acro, acro_score, align, csc_diag, csc_row, csc_score, i, j, m, 
miss_budget, miss_left, mm, n, pos, query, query_lw, record_miss, score, 
score_diag, score_row, score_up, si_lw, start, sz;
-    query = prepQuery.query;
-    query_lw = prepQuery.query_lw;
-    m = subject.length;
-    n = query.length;
-    acro = scoreAcronyms(subject, subject_lw, query, query_lw);
-    acro_score = acro.score;
-    if (acro.count === n) {
-      return scoreExact(n, m, acro_score, acro.pos);
-    }
-    pos = subject_lw.indexOf(query_lw);
-    if (pos > -1) {
-      return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m);
-    }
-    score_row = new Array(n);
-    csc_row = new Array(n);
-    sz = scoreSize(n, m);
-    miss_budget = Math.ceil(miss_coeff * n) + 5;
-    miss_left = miss_budget;
-    j = -1;
-    while (++j < n) {
-      score_row[j] = 0;
-      csc_row[j] = 0;
-    }
-    i = subject_lw.indexOf(query_lw[0]);
-    if (i > -1) {
-      i--;
-    }
-    mm = subject_lw.lastIndexOf(query_lw[n - 1], m);
-    if (mm > i) {
-      m = mm + 1;
-    }
-    while (++i < m) {
-      score = 0;
-      score_diag = 0;
-      csc_diag = 0;
-      si_lw = subject_lw[i];
-      record_miss = true;
-      j = -1;
-      while (++j < n) {
-        score_up = score_row[j];
-        if (score_up > score) {
-          score = score_up;
-        }
-        csc_score = 0;
-        if (query_lw[j] === si_lw) {
-          start = isWordStart(i, subject, subject_lw);
-          csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, 
subject_lw, query, query_lw, i, j, start);
-          align = score_diag + scoreCharacter(i, j, start, acro_score, 
csc_score);
-          if (align > score) {
-            score = align;
-            miss_left = miss_budget;
-          } else {
-            if (record_miss && --miss_left <= 0) {
-              return score_row[n - 1] * sz;
-            }
-            record_miss = false;
-          }
-        }
-        score_diag = score_up;
-        csc_diag = csc_row[j];
-        csc_row[j] = csc_score;
-        score_row[j] = score;
-      }
-    }
-    return score * sz;
-  };
-
-  exports.isWordStart = isWordStart = function(pos, subject, subject_lw) {
-    var curr_s, prev_s;
-    if (pos === 0) {
-      return true;
-    }
-    curr_s = subject[pos];
-    prev_s = subject[pos - 1];
-    return isSeparator(curr_s) || isSeparator(prev_s) || (curr_s !== 
subject_lw[pos] && prev_s === subject_lw[pos - 1]);
-  };
-
-  exports.isWordEnd = isWordEnd = function(pos, subject, subject_lw, len) {
-    var curr_s, next_s;
-    if (pos === len - 1) {
-      return true;
-    }
-    curr_s = subject[pos];
-    next_s = subject[pos + 1];
-    return isSeparator(curr_s) || isSeparator(next_s) || (curr_s === 
subject_lw[pos] && next_s !== subject_lw[pos + 1]);
-  };
-
-  isSeparator = function(c) {
-    return c === ' ' || c === '.' || c === '-' || c === '_' || c === '/' || c 
=== '\\';
-  };
-
-  scorePosition = function(pos) {
-    var sc;
-    if (pos < pos_bonus) {
-      sc = pos_bonus - pos;
-      return 100 + sc * sc;
-    } else {
-      return Math.max(100 + pos_bonus - pos, 0);
-    }
-  };
-
-  scoreSize = function(n, m) {
-    return tau_size / (tau_size + Math.abs(m - n));
-  };
-
-  scoreExact = function(n, m, quality, pos) {
-    return 2 * n * (wm * quality + scorePosition(pos)) * scoreSize(n, m);
-  };
-
-  exports.scorePattern = scorePattern = function(count, len, sameCase, start, 
end) {
-    var bonus, sz;
-    sz = count;
-    bonus = 6;
-    if (sameCase === count) {
-      bonus += 2;
-    }
-    if (start) {
-      bonus += 3;
-    }
-    if (end) {
-      bonus += 1;
-    }
-    if (count === len) {
-      if (start) {
-        if (sameCase === len) {
-          sz += 2;
-        } else {
-          sz += 1;
-        }
-      }
-      if (end) {
-        bonus += 1;
-      }
-    }
-    return sameCase + sz * (sz + bonus);
-  };
-
-  exports.scoreCharacter = scoreCharacter = function(i, j, start, acro_score, 
csc_score) {
-    var posBonus;
-    posBonus = scorePosition(i);
-    if (start) {
-      return posBonus + wm * ((acro_score > csc_score ? acro_score : 
csc_score) + 10);
-    }
-    return posBonus + wm * csc_score;
-  };
-
-  exports.scoreConsecutives = scoreConsecutives = function(subject, 
subject_lw, query, query_lw, i, j, start) {
-    var k, m, mi, n, nj, sameCase, startPos, sz;
-    m = subject.length;
-    n = query.length;
-    mi = m - i;
-    nj = n - j;
-    k = mi < nj ? mi : nj;
-    startPos = i;
-    sameCase = 0;
-    sz = 0;
-    if (query[j] === subject[i]) {
-      sameCase++;
-    }
-    while (++sz < k && query_lw[++j] === subject_lw[++i]) {
-      if (query[j] === subject[i]) {
-        sameCase++;
-      }
-    }
-    if (sz === 1) {
-      return 1 + 2 * sameCase;
-    }
-    return scorePattern(sz, n, sameCase, start, isWordEnd(i, subject, 
subject_lw, m));
-  };
-
-  exports.scoreExactMatch = scoreExactMatch = function(subject, subject_lw, 
query, query_lw, pos, n, m) {
-    var end, i, pos2, sameCase, start;
-    start = isWordStart(pos, subject, subject_lw);
-    if (!start) {
-      pos2 = subject_lw.indexOf(query_lw, pos + 1);
-      if (pos2 > -1) {
-        start = isWordStart(pos2, subject, subject_lw);
-        if (start) {
-          pos = pos2;
-        }
-      }
-    }
-    i = -1;
-    sameCase = 0;
-    while (++i < n) {
-      if (query[pos + i] === subject[i]) {
-        sameCase++;
-      }
-    }
-    end = isWordEnd(pos + n - 1, subject, subject_lw, m);
-    return scoreExact(n, m, scorePattern(n, n, sameCase, start, end), pos);
-  };
-
-  AcronymResult = (function() {
-    function AcronymResult(score, pos, count) {
-      this.score = score;
-      this.pos = pos;
-      this.count = count;
-    }
-
-    return AcronymResult;
-
-  })();
-
-  emptyAcronymResult = new AcronymResult(0, 0.1, 0);
-
-  exports.scoreAcronyms = scoreAcronyms = function(subject, subject_lw, query, 
query_lw) {
-    var count, i, j, m, n, pos, qj_lw, sameCase, score;
-    m = subject.length;
-    n = query.length;
-    if (!(m > 1 && n > 1)) {
-      return emptyAcronymResult;
-    }
-    count = 0;
-    pos = 0;
-    sameCase = 0;
-    i = -1;
-    j = -1;
-    while (++j < n) {
-      qj_lw = query_lw[j];
-      while (++i < m) {
-        if (qj_lw === subject_lw[i] && isWordStart(i, subject, subject_lw)) {
-          if (query[j] === subject[i]) {
-            sameCase++;
-          }
-          pos += i;
-          count++;
-          break;
-        }
-      }
-      if (i === m) {
-        break;
-      }
-    }
-    if (count < 2) {
-      return emptyAcronymResult;
-    }
-    score = scorePattern(count, n, sameCase, true, false);
-    return new AcronymResult(score, pos / count, count);
-  };
-
-  basenameScore = function(subject, subject_lw, prepQuery, fullPathScore) {
-    var alpha, basePathScore, basePos, depth, end;
-    if (fullPathScore === 0) {
-      return 0;
-    }
-    end = subject.length - 1;
-    while (subject[end] === PathSeparator) {
-      end--;
-    }
-    basePos = subject.lastIndexOf(PathSeparator, end);
-    if (basePos === -1) {
-      return fullPathScore;
-    }
-    depth = prepQuery.depth;
-    while (depth-- > 0) {
-      basePos = subject.lastIndexOf(PathSeparator, basePos - 1);
-      if (basePos === -1) {
-        return fullPathScore;
-      }
-    }
-    basePos++;
-    end++;
-    basePathScore = doScore(subject.slice(basePos, end), 
subject_lw.slice(basePos, end), prepQuery);
-    alpha = 0.5 * tau_depth / (tau_depth + countDir(subject, end + 1));
-    return alpha * basePathScore + (1 - alpha) * fullPathScore * scoreSize(0, 
file_coeff * (end - basePos));
-  };
-
-  exports.countDir = countDir = function(path, end) {
-    var count, i;
-    if (end < 1) {
-      return 0;
-    }
-    count = 0;
-    i = -1;
-    while (++i < end && path[i] === PathSeparator) {
-      continue;
-    }
-    while (++i < end) {
-      if (path[i] === PathSeparator) {
-        count++;
-        while (++i < end && path[i] === PathSeparator) {
-          continue;
-        }
-      }
-    }
-    return count;
-  };
-
-  truncatedUpperCase = function(str) {
-    var char, upper, _i, _len;
-    upper = "";
-    for (_i = 0, _len = str.length; _i < _len; _i++) {
-      char = str[_i];
-      upper += char.toUpperCase()[0];
-    }
-    return upper;
-  };
-
-}).call(this);
-
-},{"path":7}],7:[function(require,module,exports){
-(function (process){
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-// resolves . and .. elements in a path array with directory names there
-// must be no slashes, empty elements, or device names (c:\) in the array
-// (so also no leading and trailing slashes - it does not distinguish
-// relative and absolute paths)
-function normalizeArray(parts, allowAboveRoot) {
-  // if the path tries to go above the root, `up` ends up > 0
-  var up = 0;
-  for (var i = parts.length - 1; i >= 0; i--) {
-    var last = parts[i];
-    if (last === '.') {
-      parts.splice(i, 1);
-    } else if (last === '..') {
-      parts.splice(i, 1);
-      up++;
-    } else if (up) {
-      parts.splice(i, 1);
-      up--;
-    }
-  }
-
-  // if the path is allowed to go above the root, restore leading ..s
-  if (allowAboveRoot) {
-    for (; up--; up) {
-      parts.unshift('..');
-    }
-  }
-
-  return parts;
-}
-
-// Split a filename into [root, dir, basename, ext], unix version
-// 'root' is just a slash, or nothing.
-var splitPathRe =
-    /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
-var splitPath = function(filename) {
-  return splitPathRe.exec(filename).slice(1);
-};
-
-// path.resolve([from ...], to)
-// posix version
-exports.resolve = function() {
-  var resolvedPath = '',
-      resolvedAbsolute = false;
-
-  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
-    var path = (i >= 0) ? arguments[i] : process.cwd();
-
-    // Skip empty and invalid entries
-    if (typeof path !== 'string') {
-      throw new TypeError('Arguments to path.resolve must be strings');
-    } else if (!path) {
-      continue;
-    }
-
-    resolvedPath = path + '/' + resolvedPath;
-    resolvedAbsolute = path.charAt(0) === '/';
-  }
-
-  // At this point the path should be resolved to a full absolute path, but
-  // handle relative paths to be safe (might happen when process.cwd() fails)
-
-  // Normalize the path
-  resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
-    return !!p;
-  }), !resolvedAbsolute).join('/');
-
-  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
-};
-
-// path.normalize(path)
-// posix version
-exports.normalize = function(path) {
-  var isAbsolute = exports.isAbsolute(path),
-      trailingSlash = substr(path, -1) === '/';
-
-  // Normalize the path
-  path = normalizeArray(filter(path.split('/'), function(p) {
-    return !!p;
-  }), !isAbsolute).join('/');
-
-  if (!path && !isAbsolute) {
-    path = '.';
-  }
-  if (path && trailingSlash) {
-    path += '/';
-  }
-
-  return (isAbsolute ? '/' : '') + path;
-};
-
-// posix version
-exports.isAbsolute = function(path) {
-  return path.charAt(0) === '/';
-};
-
-// posix version
-exports.join = function() {
-  var paths = Array.prototype.slice.call(arguments, 0);
-  return exports.normalize(filter(paths, function(p, index) {
-    if (typeof p !== 'string') {
-      throw new TypeError('Arguments to path.join must be strings');
-    }
-    return p;
-  }).join('/'));
-};
-
-
-// path.relative(from, to)
-// posix version
-exports.relative = function(from, to) {
-  from = exports.resolve(from).substr(1);
-  to = exports.resolve(to).substr(1);
-
-  function trim(arr) {
-    var start = 0;
-    for (; start < arr.length; start++) {
-      if (arr[start] !== '') break;
-    }
-
-    var end = arr.length - 1;
-    for (; end >= 0; end--) {
-      if (arr[end] !== '') break;
-    }
-
-    if (start > end) return [];
-    return arr.slice(start, end - start + 1);
-  }
-
-  var fromParts = trim(from.split('/'));
-  var toParts = trim(to.split('/'));
-
-  var length = Math.min(fromParts.length, toParts.length);
-  var samePartsLength = length;
-  for (var i = 0; i < length; i++) {
-    if (fromParts[i] !== toParts[i]) {
-      samePartsLength = i;
-      break;
-    }
-  }
-
-  var outputParts = [];
-  for (var i = samePartsLength; i < fromParts.length; i++) {
-    outputParts.push('..');
-  }
-
-  outputParts = outputParts.concat(toParts.slice(samePartsLength));
-
-  return outputParts.join('/');
-};
-
-exports.sep = '/';
-exports.delimiter = ':';
-
-exports.dirname = function(path) {
-  var result = splitPath(path),
-      root = result[0],
-      dir = result[1];
-
-  if (!root && !dir) {
-    // No dirname whatsoever
-    return '.';
-  }
-
-  if (dir) {
-    // It has a dirname, strip trailing slash
-    dir = dir.substr(0, dir.length - 1);
-  }
-
-  return root + dir;
-};
-
-
-exports.basename = function(path, ext) {
-  var f = splitPath(path)[2];
-  // TODO: make this comparison case-insensitive on windows?
-  if (ext && f.substr(-1 * ext.length) === ext) {
-    f = f.substr(0, f.length - ext.length);
-  }
-  return f;
-};
-
-
-exports.extname = function(path) {
-  return splitPath(path)[3];
-};
-
-function filter (xs, f) {
-    if (xs.filter) return xs.filter(f);
-    var res = [];
-    for (var i = 0; i < xs.length; i++) {
-        if (f(xs[i], i, xs)) res.push(xs[i]);
-    }
-    return res;
-}
-
-// String.prototype.substr - negative index don't work in IE8
-var substr = 'ab'.substr(-1) === 'b'
-    ? function (str, start, len) { return str.substr(start, len) }
-    : function (str, start, len) {
-        if (start < 0) start = str.length + start;
-        return str.substr(start, len);
-    }
-;
-
-}).call(this,require('_process'))
-},{"_process":8}],8:[function(require,module,exports){
-// shim for using process in browser
-
-var process = module.exports = {};
-var queue = [];
-var draining = false;
-var currentQueue;
-var queueIndex = -1;
-
-function cleanUpNextTick() {
-    draining = false;
-    if (currentQueue.length) {
-        queue = currentQueue.concat(queue);
-    } else {
-        queueIndex = -1;
-    }
-    if (queue.length) {
-        drainQueue();
-    }
-}
-
-function drainQueue() {
-    if (draining) {
-        return;
-    }
-    var timeout = setTimeout(cleanUpNextTick);
-    draining = true;
-
-    var len = queue.length;
-    while(len) {
-        currentQueue = queue;
-        queue = [];
-        while (++queueIndex < len) {
-            if (currentQueue) {
-                currentQueue[queueIndex].run();
-            }
-        }
-        queueIndex = -1;
-        len = queue.length;
-    }
-    currentQueue = null;
-    draining = false;
-    clearTimeout(timeout);
-}
-
-process.nextTick = function (fun) {
-    var args = new Array(arguments.length - 1);
-    if (arguments.length > 1) {
-        for (var i = 1; i < arguments.length; i++) {
-            args[i - 1] = arguments[i];
-        }
-    }
-    queue.push(new Item(fun, args));
-    if (queue.length === 1 && !draining) {
-        setTimeout(drainQueue, 0);
-    }
-};
-
-// v8 likes predictible objects
-function Item(fun, array) {
-    this.fun = fun;
-    this.array = array;
-}
-Item.prototype.run = function () {
-    this.fun.apply(null, this.array);
-};
-process.title = 'browser';
-process.browser = true;
-process.env = {};
-process.argv = [];
-process.version = ''; // empty string to avoid regexp issues
-process.versions = {};
-
-function noop() {}
-
-process.on = noop;
-process.addListener = noop;
-process.once = noop;
-process.off = noop;
-process.removeListener = noop;
-process.removeAllListeners = noop;
-process.emit = noop;
-
-process.binding = function (name) {
-    throw new Error('process.binding is not supported');
-};
-
-process.cwd = function () { return '/' };
-process.chdir = function (dir) {
-    throw new Error('process.chdir is not supported');
-};
-process.umask = function() { return 0; };
-
-},{}]},{},[1]);

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to