Merge pull request #716 from haberman/fixruby

Fixed several Ruby conformance test cases through upb update.
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 6c91e13..33e069f 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -1,13 +1,42 @@
+# Minimum CMake required
 cmake_minimum_required(VERSION 2.8)
 
+# Project
 project(protobuf C CXX)
 
+# Options
 option(BUILD_TESTING "Build tests" ON)
 option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
 if (MSVC)
   option(ZLIB "Build with zlib support" OFF)
 endif (MSVC)
 
+# Path to main configure script
+set(protobuf_CONFIGURE_SCRIPT "../configure.ac")
+
+# Parse version from configure script
+file(STRINGS "${protobuf_CONFIGURE_SCRIPT}" protobuf_VERSION_LINE
+  LIMIT_COUNT 1
+  REGEX "^AC_INIT")
+# Replace special characters
+string(REPLACE "(" "_" protobuf_VERSION_LINE ${protobuf_VERSION_LINE})
+string(REPLACE ")" "_" protobuf_VERSION_LINE ${protobuf_VERSION_LINE})
+string(REPLACE "[" "_" protobuf_VERSION_LINE ${protobuf_VERSION_LINE})
+string(REPLACE "]" "_" protobuf_VERSION_LINE ${protobuf_VERSION_LINE})
+# Parse version string
+string(REGEX REPLACE "^AC_INIT__Protocol Buffers_,_([^_]+).*$" "\\1"
+    protobuf_VERSION_STRING "${protobuf_VERSION_LINE}")
+# Parse version tweaks
+string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*$" "\\1"
+  protobuf_VERSION_MAJOR "${protobuf_VERSION_STRING}")
+string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*$" "\\2"
+  protobuf_VERSION_MINOR "${protobuf_VERSION_STRING}")
+string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*$" "\\3"
+  protobuf_VERSION_PATCH "${protobuf_VERSION_STRING}")
+# Package version
+set(protobuf_VERSION
+  "${protobuf_VERSION_MAJOR}.${protobuf_VERSION_MINOR}.${protobuf_VERSION_PATCH}")
+
 add_definitions(-DGOOGLE_PROTOBUF_CMAKE_BUILD)
 
 find_package(Threads REQUIRED)
@@ -86,6 +115,9 @@
 include(libprotobuf.cmake)
 include(libprotoc.cmake)
 include(protoc.cmake)
+
 if (BUILD_TESTING)
   include(tests.cmake)
 endif (BUILD_TESTING)
+
+include(install.cmake)
diff --git a/cmake/install.cmake b/cmake/install.cmake
new file mode 100644
index 0000000..e14ef1d
--- /dev/null
+++ b/cmake/install.cmake
@@ -0,0 +1,103 @@
+include(GNUInstallDirs)

+

+foreach(_library

+  libprotobuf-lite

+  libprotobuf

+  libprotoc)

+  set_property(TARGET ${_library}

+    PROPERTY INTERFACE_INCLUDE_DIRECTORIES

+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

+  install(TARGETS ${_library} EXPORT protobuf-targets

+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}

+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}

+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library})

+endforeach()

+

+install(TARGETS protoc EXPORT protobuf-targets

+  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)

+

+if(TRUE)

+  file(STRINGS extract_includes.bat.in _extract_strings

+    REGEX "^copy")

+  foreach(_extract_string ${_extract_strings})

+    string(REPLACE "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\" ""

+      _extract_string ${_extract_string})

+    string(REPLACE "\\" "/" _extract_string ${_extract_string})

+    string(REGEX MATCH "^[^ ]+"

+      _extract_from ${_extract_string})

+    string(REGEX REPLACE "^${_extract_from} ([^$]+)" "\\1"

+      _extract_to ${_extract_string})

+    get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/${_extract_from}" ABSOLUTE)

+    get_filename_component(_extract_name ${_extract_to} NAME)

+    get_filename_component(_extract_to ${_extract_to} PATH)

+    string(REPLACE "include/" "${CMAKE_INSTALL_INCLUDEDIR}/"

+      _extract_to "${_extract_to}")

+    if(EXISTS "${_extract_from}")

+      install(FILES "${_extract_from}"

+        DESTINATION "${_extract_to}"

+        COMPONENT protobuf-headers

+        RENAME "${_extract_name}")

+    else()

+      message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "

+        "\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "

+        "but there not exists. The file will not be installed.")

+    endif()

+  endforeach()

+endif()

+

+# Internal function for parsing auto tools scripts

+function(_protobuf_auto_list FILE_NAME VARIABLE)

+  file(STRINGS ${FILE_NAME} _strings)

+  set(_list)

+  foreach(_string ${_strings})

+    set(_found)

+    string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")

+    if(_found)

+      string(LENGTH "${_found}" _length)

+      string(SUBSTRING "${_string}" ${_length} -1 _draft_list)

+      foreach(_item ${_draft_list})

+        string(STRIP "${_item}" _item)

+        list(APPEND _list "${_item}")

+      endforeach()

+    endif()

+  endforeach()

+  set(${VARIABLE} ${_list} PARENT_SCOPE)

+endfunction()

+

+# Install well-known type proto files

+_protobuf_auto_list("../src/Makefile.am" nobase_dist_proto_DATA)

+foreach(_file ${nobase_dist_proto_DATA})

+  get_filename_component(_file_from "../src/${_file}" ABSOLUTE)

+  get_filename_component(_file_name ${_file} NAME)

+  get_filename_component(_file_path ${_file} PATH)

+  if(EXISTS "${_file_from}")

+    install(FILES "${_file_from}"

+      DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_file_path}"

+      COMPONENT protobuf-protos

+      RENAME "${_file_name}")

+  else()

+    message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "

+      "\"${protobuf_SOURCE_DIR}/../src/Makefile.am\" as nobase_dist_proto_DATA "

+      "but there not exists. The file will not be installed.")

+  endif()

+endforeach()

+

+# Export configuration

+

+install(EXPORT protobuf-targets

+  DESTINATION "lib/cmake/protobuf"

+  COMPONENT protobuf-export)

+

+configure_file(protobuf-config.cmake.in

+  protobuf-config.cmake @ONLY)

+configure_file(protobuf-config-version.cmake.in

+  protobuf-config-version.cmake @ONLY)

+configure_file(protobuf-module.cmake.in

+  protobuf-module.cmake @ONLY)

+

+install(FILES

+  "${protobuf_BINARY_DIR}/protobuf-config.cmake"

+  "${protobuf_BINARY_DIR}/protobuf-config-version.cmake"

+  "${protobuf_BINARY_DIR}/protobuf-module.cmake"

+  DESTINATION "lib/cmake/protobuf"

+  COMPONENT protobuf-export)

diff --git a/cmake/protobuf-config-version.cmake.in b/cmake/protobuf-config-version.cmake.in
new file mode 100644
index 0000000..07ab40b
--- /dev/null
+++ b/cmake/protobuf-config-version.cmake.in
@@ -0,0 +1 @@
+set(PACKAGE_VERSION @protobuf_VERSION@)

diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
new file mode 100644
index 0000000..51d715c
--- /dev/null
+++ b/cmake/protobuf-config.cmake.in
@@ -0,0 +1,27 @@
+# Version info variables

+set(PROTOBUF_VERSION        "@protobuf_VERSION@")

+set(PROTOBUF_VERSION_STRING "@protobuf_VERSION_STRING@")

+

+# Current dir

+get_filename_component(_PROTOBUF_PACKAGE_PREFIX

+  "${CMAKE_CURRENT_LIST_FILE}" PATH)

+

+# Imported targets

+include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-targets.cmake")

+

+# Compute the installation prefix relative to this file.

+get_filename_component(_PROTOBUF_IMPORT_PREFIX

+  "${_PROTOBUF_PACKAGE_PREFIX}" PATH)

+get_filename_component(_PROTOBUF_IMPORT_PREFIX

+  "${_PROTOBUF_IMPORT_PREFIX}" PATH)

+get_filename_component(_PROTOBUF_IMPORT_PREFIX

+  "${_PROTOBUF_IMPORT_PREFIX}" PATH)

+

+# CMake FindProtobuf module compatible file

+if(NOT DEFINED PROTOBUF_MODULE_COMPATIBLE OR "${PROTOBUF_MODULE_COMPATIBLE}")

+  include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-module.cmake")

+endif()

+

+# Cleanup temporary variables.

+set(_PROTOBUF_PACKAGE_PREFIX)

+set(_PROTOBUF_IMPORT_PREFIX)

diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in
new file mode 100644
index 0000000..d81dc45
--- /dev/null
+++ b/cmake/protobuf-module.cmake.in
@@ -0,0 +1,139 @@
+if(PROTOBUF_SRC_ROOT_FOLDER)
+  message(AUTHOR_WARNING "Variable PROTOBUF_SRC_ROOT_FOLDER defined, but not"
+    " used in CONFIG mode")
+endif()
+
+function(PROTOBUF_GENERATE_CPP SRCS HDRS)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
+    return()
+  endif()
+
+  if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
+    # Create an include path for each file specified
+    foreach(FIL ${ARGN})
+      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+      get_filename_component(ABS_PATH ${ABS_FIL} PATH)
+      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${ABS_PATH})
+      endif()
+    endforeach()
+  else()
+    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+  endif()
+
+  # Add well-known type protos include path
+  list(APPEND _protobuf_include_path
+    -I "${_PROTOBUF_IMPORT_PREFIX}/@CMAKE_INSTALL_INCLUDEDIR@")
+
+  if(DEFINED PROTOBUF_IMPORT_DIRS)
+    foreach(DIR ${PROTOBUF_IMPORT_DIRS})
+      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
+      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${ABS_PATH})
+      endif()
+    endforeach()
+  endif()
+
+  set(${SRCS})
+  set(${HDRS})
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+
+    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
+    list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
+
+    add_custom_command(
+      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
+             "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
+      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+      ARGS --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
+      DEPENDS ${ABS_FIL} ${PROTOBUF_PROTOC_EXECUTABLE}
+      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
+      VERBATIM)
+  endforeach()
+
+  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
+  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+  set(${HDRS} ${${HDRS}} PARENT_SCOPE)
+endfunction()
+
+# Internal function: search for normal library as well as a debug one
+#    if the debug one is specified also include debug/optimized keywords
+#    in *_LIBRARIES variable
+function(_protobuf_find_libraries name filename)
+   get_target_property(${name}_LIBRARY lib${filename}
+     IMPORTED_LOCATION_RELEASE)
+   set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE)
+   get_target_property(${name}_LIBRARY_DEBUG lib${filename}
+     IMPORTED_LOCATION_DEBUG)
+   set(${name}_LIBRARY_DEBUG "${${name}_LIBRARY_DEBUG}" PARENT_SCOPE)
+
+   if(NOT ${name}_LIBRARY_DEBUG)
+      # There is no debug library
+      set(${name}_LIBRARY_DEBUG ${${name}_LIBRARY} PARENT_SCOPE)
+      set(${name}_LIBRARIES     ${${name}_LIBRARY} PARENT_SCOPE)
+   else()
+      # There IS a debug library
+      set(${name}_LIBRARIES
+          optimized ${${name}_LIBRARY}
+          debug     ${${name}_LIBRARY_DEBUG}
+          PARENT_SCOPE
+      )
+   endif()
+endfunction()
+
+# Internal function: find threads library
+function(_protobuf_find_threads)
+    set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+    find_package(Threads)
+    if(Threads_FOUND)
+        list(APPEND PROTOBUF_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+        set(PROTOBUF_LIBRARIES "${PROTOBUF_LIBRARIES}" PARENT_SCOPE)
+    endif()
+endfunction()
+
+#
+# Main.
+#
+
+# By default have PROTOBUF_GENERATE_CPP macro pass -I to protoc
+# for each directory where a proto file is referenced.
+if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH)
+  set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE)
+endif()
+
+# The Protobuf library
+_protobuf_find_libraries(PROTOBUF protobuf)
+
+# The Protobuf Lite library
+_protobuf_find_libraries(PROTOBUF_LITE protobuf-lite)
+
+# The Protobuf Protoc Library
+_protobuf_find_libraries(PROTOBUF_PROTOC protoc)
+
+if(UNIX)
+  _protobuf_find_threads()
+endif()
+
+# Set the include directory
+set(PROTOBUF_INCLUDE_DIR "${_PROTOBUF_IMPORT_PREFIX}/@CMAKE_INSTALL_INCLUDEDIR@")
+
+# Set the protoc Executable
+get_target_property(PROTOBUF_PROTOC_EXECUTABLE protoc
+  IMPORTED_LOCATION_RELEASE)
+if(NOT PROTOBUF_PROTOC_EXECUTABLE)
+  get_target_property(PROTOBUF_PROTOC_EXECUTABLE protoc
+    IMPORTED_LOCATION_DEBUG)
+endif()
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG
+    PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR)
+
+if(PROTOBUF_FOUND)
+    set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
+endif()
diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
index 500e467..bad58fa 100644
--- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
@@ -368,5 +368,20 @@
         {
             return "FileDescriptor for " + proto.Name;
         }
+
+        /// <summary>
+        /// Returns the file descriptor for descriptor.proto.
+        /// </summary>
+        /// <remarks>
+        /// This is used for protos which take a direct dependency on <c>descriptor.proto</c>, typically for
+        /// annotations. While <c>descriptor.proto</c> is a proto2 file, it is built into the Google.Protobuf
+        /// runtime for reflection purposes. The messages are internal to the runtime as they would require
+        /// proto2 semantics for full support, but the file descriptor is available via this property. The
+        /// C# codegen in protoc automatically uses this property when it detects a dependency on <c>descriptor.proto</c>.
+        /// </remarks>
+        /// <value>
+        /// The file descriptor for <c>descriptor.proto</c>.
+        /// </value>
+        public static FileDescriptor DescriptorProtoFileDescriptor { get { return DescriptorProtoFile.Descriptor; } }
     }
 }
\ No newline at end of file
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index 1d17af6..278e05f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -117,7 +117,10 @@
 inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
   // TODO: Do this better! (Currently this depends on a hack in generate_protos.sh to rename
   // the file...)
-  return descriptor->name() == "google/protobuf/descriptor_proto_file.proto";
+  // We need to be able to detect the "normal" name as well, for times that we're just
+  // depending on descriptor.proto instead of generating it.
+  return descriptor->name() == "google/protobuf/descriptor_proto_file.proto"
+      || descriptor->name() == "google/protobuf/descriptor.proto";
 }
 
 inline bool IsWrapperType(const FieldDescriptor* descriptor) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
index 0ffae3d..399c64e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -180,10 +180,17 @@
       "descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n");
   printer->Print("    new pbr::FileDescriptor[] { ");
   for (int i = 0; i < file_->dependency_count(); i++) {
-    printer->Print(
+    // descriptor.proto is special: we don't allow access to the generated code, but there's
+    // a separately-exposed property to get at the file descriptor, specifically to allow this
+    // kind of dependency.
+    if (IsDescriptorProto(file_->dependency(i))) {
+      printer->Print("pbr::FileDescriptor.DescriptorProtoFileDescriptor, ");
+    } else {
+      printer->Print(
       "$full_umbrella_class_name$.Descriptor, ",
       "full_umbrella_class_name",
       GetUmbrellaClassName(file_->dependency(i)));
+    }
   }
   printer->Print("},\n"
       "    new pbr::GeneratedCodeInfo(");