allow for soft updating of global-requirements

This creates a devstack REQUIREMENTS_MODE which is how we handle
syncing of global requirements. The default is 'strict', which is
current behavior. There is a new 'soft' mode which does a
--soft-update for projects *not* found in projects.txt, which lets
them specify additional requirements.

Change-Id: I4aa606514131b5dde67d87f5c8db5a3f3e50fc03
Depends-On: I1f195ef9ff1509659848e14ec9936ff6f66a6496
diff --git a/functions-common b/functions-common
index e6f425f..9041439 100644
--- a/functions-common
+++ b/functions-common
@@ -1606,6 +1606,16 @@
     setup_package_with_req_sync $project_dir -e
 }
 
+# determine if a project as specified by directory is in
+# projects.txt. This will not be an exact match because we throw away
+# the namespacing when we clone, but it should be good enough in all
+# practical ways.
+function is_in_projects_txt {
+    local project_dir=$1
+    local project_name=$(basename $project_dir)
+    return grep "/$project_name\$" $REQUIREMENTS_DIR/projects.txt >/dev/null
+}
+
 # ``pip install -e`` the package, which processes the dependencies
 # using pip before running `setup.py develop`
 #
@@ -1624,8 +1634,19 @@
     local update_requirements=$(cd $project_dir && git diff --exit-code >/dev/null || echo "changed")
 
     if [[ $update_requirements != "changed" ]]; then
-        (cd $REQUIREMENTS_DIR; \
-            python update.py $project_dir)
+        if [[ "$REQUIREMENTS_MODE" == "soft" ]]; then
+            if is_in_projects_txt $project_dir; then
+                (cd $REQUIREMENTS_DIR; \
+                    python update.py $project_dir)
+            else
+                # soft update projects not found in requirements project.txt
+                (cd $REQUIREMENTS_DIR; \
+                    python update.py -s $project_dir)
+            fi
+        else
+            (cd $REQUIREMENTS_DIR; \
+                python update.py $project_dir)
+        fi
     fi
 
     setup_package $project_dir $flags