{"action":"created","comment":{"url":"https://api.github.com/repos/mono/mono/pulls/comments/27851097","id":27851097,"diff_hunk":"@@ -2490,6 +2541,517 @@ counters_and_perfcounters_sample (MonoProfiler *prof)\n \tperfcounters_sample (prof, (now - start) / 1000/ 1000);\n }\n \n+#define COVERAGE_DEBUG(x) if (debug_coverage) {x}\n+static GHashTable *coverage_methods = NULL;\n+static GHashTable *coverage_assemblies = NULL;\n+static GHashTable *coverage_classes = NULL;\n+static GHashTable *filtered_classes = NULL;\n+static GHashTable *entered_methods = NULL;\n+static GHashTable *image_to_methods = NULL;\n+static GHashTable *suppressed_assemblies = NULL;\n+static gboolean coverage_initialized = FALSE;\n+static mono_mutex_t coverage_mutex;\n+static GPtrArray *coverage_data = NULL;\n+static int previous_offset = 0;\n+\n+typedef struct _CoverageEntry CoverageEntry;\n+struct _CoverageEntry {\n+\tint offset;\n+\tint counter;\n+\tchar *filename;\n+\tint line;\n+\tint column;\n+};\n+\n+static void\n+free_coverage_entry (gpointer data, gpointer userdata)\n+{\n+\tCoverageEntry *entry = (CoverageEntry *)data;\n+\tg_free (entry->filename);\n+\tg_free (entry);\n+}\n+\n+static void\n+obtain_coverage_for_method (MonoProfiler *prof, const MonoProfileCoverageEntry *entry)\n+{\n+\tint offset = entry->iloffset - previous_offset;\n+\tCoverageEntry *e = g_new (CoverageEntry, 1);\n+\n+\tprevious_offset = entry->iloffset;\n+\n+\te->offset = offset;\n+\te->counter = entry->counter;\n+\te->filename = g_strdup(entry->filename ? entry->filename : \"\");\n+\te->line = entry->line;\n+\te->column = entry->col;\n+\n+\tg_ptr_array_add (coverage_data, e);\n+}\n+\n+static char *\n+parse_generic_type_names(char *name)\n+{\n+\tchar *new_name,*ret;\n+\tint within_generic_declaration=0, generic_members=1;\n+\n+\tif (name == NULL || *name == '\\0')\n+\t\treturn g_strdup (\"\");\n+\n+\tif( !(ret = new_name = calloc(strlen(name) * 4 + 1, sizeof(char))) )\n+\t\treturn NULL;\n+\n+\tdo\n+\t{\n+\t\tswitch(*name)\n+\t\t{\n+\t\t\tcase '<':\n+\t\t\t\twithin_generic_declaration = 1;\n+\t\t\t\tbreak;\n+\t\t\tcase '>':\n+\t\t\t\twithin_generic_declaration = 0;\n+\t\t\t\tif( *(name-1) != '<')\n+\t\t\t\t{\n+\t\t\t\t\t*new_name++ = '`';\n+\t\t\t\t\t*new_name++ = '0' + generic_members;\n+\t\t\t\t}\n+\t\t\t\telse\n+\t\t\t\t{\n+\t\t\t\t\tmemcpy(new_name,\"&lt;&gt;\",8);\n+\t\t\t\t\tnew_name+=8;\n+\t\t\t\t}\n+\t\t\t\tgeneric_members = 0;\n+\t\t\t\tbreak;\n+\t\t\tcase ',':\n+\t\t\t\tgeneric_members++;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tif(!within_generic_declaration)\n+\t\t\t\t\t*new_name++ = *name;\n+\t\t\t\tbreak;\n+\t\t}\n+\t}while(*name++);\n+\treturn ret;\n+}\n+\n+static int method_id;\n+static void\n+build_method_buffer (gpointer key, gpointer value, gpointer userdata)\n+{\n+\tMonoMethod *method = (MonoMethod *)value;\n+\tMonoProfiler *prof = (MonoProfiler *)userdata;\n+\tMonoClass *klass;\n+\tMonoImage *image;\n+\tchar *class_name;\n+\tconst char *image_name, *method_name, *sig, *first_filename;\n+\tLogBuffer *logbuffer;\n+\tint size = 1;\n+\tguint i;\n+\n+\tprevious_offset = 0;\n+\tcoverage_data = g_ptr_array_new ();\n+\n+\tmono_profiler_coverage_get (prof, method, obtain_coverage_for_method);\n+\n+\tklass = mono_method_get_class (method);\n+\timage = mono_class_get_image (klass);\n+\timage_name = mono_image_get_name (image);\n+\n+\tsig = mono_signature_get_desc (mono_method_signature (method), TRUE);\n+\tclass_name = parse_generic_type_names (mono_type_get_name (mono_class_get_type (klass)));\n+\tmethod_name = mono_method_get_name (method);\n+\n+\tif (coverage_data->len != 0) {\n+\t\tCoverageEntry *entry = coverage_data->pdata[0];\n+\t\tfirst_filename = entry->filename ? entry->filename : \"\";\n+\t} else {\n+\t\tfirst_filename = \"\";\n+\t}\n+\n+\timage_name = image_name ? image_name : \"\";\n+\tsig = sig ? sig : \"\";\n+\tmethod_name = method_name ? method_name : \"\";\n+\n+\tsize += strlen (image_name) + 1;\n+\tsize += strlen (class_name) + 1;\n+\tsize += strlen (method_name) + 1;\n+\tsize += strlen (first_filename) + 1;\n+\tsize += strlen (sig) + 1;\n+\n+\tsize += 10 + 10 + 5; /* token + method_id + n_entries*/\n+\n+\tlogbuffer = ensure_logbuf (size);\n+\tENTER_LOG (logbuffer, \"coverage-methods\");\n+\n+\temit_byte (logbuffer, TYPE_COVERAGE_METHOD | TYPE_COVERAGE);\n+\temit_string (logbuffer, image_name, strlen (image_name) + 1);\n+\temit_string (logbuffer, class_name, strlen (class_name) + 1);\n+\temit_string (logbuffer, method_name, strlen (method_name) + 1);\n+\temit_string (logbuffer, sig, strlen (sig) + 1);\n+\temit_string (logbuffer, first_filename, strlen (first_filename) + 1);\n+\n+\temit_uvalue (logbuffer, mono_method_get_token (method));\n+\temit_uvalue (logbuffer, method_id);\n+\temit_value (logbuffer, coverage_data->len);\n+\n+\tEXIT_LOG (logbuffer);\n+\tsafe_send (prof, ensure_logbuf (0));\n+\n+\tfor (i = 0; i < coverage_data->len; i++) {\n+\t\tCoverageEntry *entry = coverage_data->pdata[i];\n+\n+\t\tsize = 1;\n+\t\tsize += 10 * 5; /* method_id, offset, count, line, column */\n+\n+\t\tlogbuffer = ensure_logbuf (size);\n+\t\tENTER_LOG (logbuffer, \"coverage-statement\");\n+\n+\t\temit_byte (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);\n+\t\temit_uvalue (logbuffer, method_id);\n+\t\temit_uvalue (logbuffer, entry->offset);\n+\t\temit_uvalue (logbuffer, entry->counter);\n+\t\temit_uvalue (logbuffer, entry->line);\n+\t\temit_uvalue (logbuffer, entry->column);\n+\n+\t\tEXIT_LOG (logbuffer);\n+\t\tsafe_send (prof, ensure_logbuf (0));\n+\t}\n+\n+\tmethod_id++;\n+\n+\tg_free (class_name);\n+\n+\tg_ptr_array_foreach (coverage_data, free_coverage_entry, NULL);\n+\tg_ptr_array_free (coverage_data, TRUE);\n+\tcoverage_data = NULL;\n+}\n+\n+static void\n+build_class_buffer (gpointer key, gpointer value, gpointer userdata)\n+{\n+\tMonoClass *klass = (MonoClass *)key;\n+\tGPtrArray *class_methods = (GPtrArray *)value;\n+\tMonoProfiler *prof = (MonoProfiler *)userdata;\n+\tMonoImage *image;\n+\tchar *class_name;\n+\tconst char *assembly_name;\n+\tint number_of_methods, partially_covered;\n+\tguint fully_covered;\n+\tLogBuffer *logbuffer;\n+\tint size = 1;\n+\n+\timage = mono_class_get_image (klass);\n+\tassembly_name = mono_image_get_name (image);\n+\tclass_name = mono_type_get_name (mono_class_get_type (klass));\n+\n+\tassembly_name = assembly_name ? assembly_name : \"\";\n+\tnumber_of_methods = mono_class_num_methods (klass);\n+\tfully_covered = class_methods->len;\n+\t/* We don't handle partial covered yet */\n+\tpartially_covered = 0;\n+\n+\tsize += strlen (assembly_name) + 1;\n+\tsize += strlen (class_name) + 1;\n+\tsize += 30; /* number_of_methods, fully_covered, partially_covered */\n+\n+\tlogbuffer = ensure_logbuf (size);\n+\n+\tENTER_LOG (logbuffer, \"coverage-class\");\n+\temit_byte (logbuffer, TYPE_COVERAGE_CLASS | TYPE_COVERAGE);\n+\temit_string (logbuffer, assembly_name, strlen (assembly_name) + 1);\n+\temit_string (logbuffer, class_name, strlen (class_name) + 1);\n+\temit_uvalue (logbuffer, number_of_methods);\n+\temit_uvalue (logbuffer, fully_covered);\n+\temit_uvalue (logbuffer, partially_covered);\n+\tEXIT_LOG (logbuffer);\n+\n+\tsafe_send (prof, ensure_logbuf (0));\n+\n+\tg_free (class_name);\n+}\n+\n+static void\n+get_coverage_for_image (MonoImage *image, int *number_of_methods, guint *fully_covered, int *partially_covered)\n+{\n+\tGPtrArray *image_methods = g_hash_table_lookup (image_to_methods, image);\n+\n+\t*number_of_methods = mono_image_get_table_rows (image, MONO_TABLE_METHOD);\n+\tif (image_methods) {\n+\t\t*fully_covered = image_methods->len;\n+\t} else {\n+\t\t*fully_covered = 0;\n+\t}\n+\n+\t// FIXME: We don't handle partially covered yet.\n+\t*partially_covered = 0;\n+}\n+\n+static void\n+build_assembly_buffer (gpointer key, gpointer value, gpointer userdata)\n+{\n+\tMonoAssembly *assembly = (MonoAssembly *)value;\n+\tMonoProfiler *prof = (MonoProfiler *)userdata;\n+\tMonoImage *image = mono_assembly_get_image (assembly);\n+\tLogBuffer *logbuffer;\n+\tconst char *name, *guid, *filename;\n+\tint size = 1;\n+\tint number_of_methods = 0, partially_covered = 0;\n+\tguint fully_covered = 0;\n+\n+\tname = mono_image_get_name (image);\n+\tguid = mono_image_get_guid (image);\n+\tfilename = mono_image_get_filename (image);\n+\n+\tname = name ? name : \"\";\n+\tguid = guid ? guid : \"\";\n+\tfilename = filename ? filename : \"\";\n+\n+\tget_coverage_for_image (image, &number_of_methods, &fully_covered, &partially_covered);\n+\n+\tsize += strlen (name) + 1;\n+\tsize += strlen (guid) + 1;\n+\tsize += strlen (filename) + 1;\n+\tsize += 30; /* number_of_methods, fully_covered, partially_covered */\n+\tlogbuffer = ensure_logbuf (size);\n+\n+\tENTER_LOG (logbuffer, \"coverage-assemblies\");\n+\temit_byte (logbuffer, TYPE_COVERAGE_ASSEMBLY | TYPE_COVERAGE);\n+\temit_string (logbuffer, name, strlen (name) + 1);\n+\temit_string (logbuffer, guid, strlen (guid) + 1);\n+\temit_string (logbuffer, filename, strlen (filename) + 1);\n+\temit_uvalue (logbuffer, number_of_methods);\n+\temit_uvalue (logbuffer, fully_covered);\n+\temit_uvalue (logbuffer, partially_covered);\n+\tEXIT_LOG (logbuffer);\n+\n+\tsafe_send (prof, ensure_logbuf (0));\n+}\n+\n+static void\n+dump_coverage (MonoProfiler *prof)\n+{\n+\tif (!coverage_initialized)\n+\t\treturn;\n+\n+\tCOVERAGE_DEBUG(fprintf (stderr, \"Coverage: Started dump\\n\");)\n+\tmono_mutex_lock (&coverage_mutex);\n+\tmethod_id = 0;\n+\n+\tCOVERAGE_DEBUG(fprintf (stderr, \"   Dumping %d assemblies\\n\", g_hash_table_size (coverage_assemblies));)\n+\tg_hash_table_foreach (coverage_assemblies, build_assembly_buffer, prof);\n+\n+\tCOVERAGE_DEBUG(fprintf (stderr, \"   Dumping %d classes\\n\", g_hash_table_size (coverage_classes));)\n+\tg_hash_table_foreach (coverage_classes, build_class_buffer, prof);\n+\n+\tCOVERAGE_DEBUG(fprintf (stderr, \"   Dumping %d methods\\n\", g_hash_table_size (coverage_methods));)\n+\tg_hash_table_foreach (coverage_methods, build_method_buffer, prof);\n+\n+\tmono_mutex_unlock (&coverage_mutex);\n+\tCOVERAGE_DEBUG(fprintf (stderr, \"Coverage: Finished dump\\n\");)\n+}\n+\n+static void\n+process_method_enter (MonoProfiler *prof, MonoMethod *method)\n+{\n+\tMonoClass *klass;\n+\tMonoImage *image;\n+\n+\tif (!coverage_initialized)\n+\t\treturn;\n+\n+\tmono_mutex_lock (&coverage_mutex);\n+\n+\tklass = mono_method_get_class (method);\n+\timage = mono_class_get_image (klass);\n+\n+\tif (g_hash_table_lookup (suppressed_assemblies, mono_image_get_name (image))) {\n+\t\tmono_mutex_unlock (&coverage_mutex);\n+\t\treturn;\n+\t}\n+\n+\tg_hash_table_insert (entered_methods, method, method);\n+\tmono_mutex_unlock (&coverage_mutex);\n+}\n+\n+static gboolean\n+coverage_filter (MonoProfiler *prof, MonoMethod *method)\n+{\n+\tMonoClass *klass;\n+\tMonoImage *image;\n+\tMonoAssembly *assembly;\n+\tMonoMethodHeader *header;\n+\tguint32 iflags, flags, code_size;\n+\tchar *fqn, *classname;\n+\tgboolean has_positive, found;\n+\tGPtrArray *image_methods, *class_methods;\n+\n+\tif (!coverage_initialized)\n+\t\treturn FALSE;\n+\n+\tCOVERAGE_DEBUG(fprintf (stderr, \"Coverage filter for %s\\n\", mono_method_get_name (method));)\n+\n+\tflags = mono_method_get_flags (method, &iflags);\n+\tif ((iflags & 0x1000 /*METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL*/) ||\n+\t    (flags & 0x2000 /*METHOD_ATTRIBUTE_PINVOKE_IMPL*/)) {\n+\t\tCOVERAGE_DEBUG(fprintf (stderr, \"   Internal call or pinvoke - ignoring\\n\");)\n+\t\treturn FALSE;\n+\t}\n+\n+\tmono_mutex_lock (&coverage_mutex);\n+\n+\t// Don't need to do anything else if we're already tracking this method\n+\tif (g_hash_table_lookup (coverage_methods, method)) {\n+\t\tCOVERAGE_DEBUG(fprintf (stderr, \"   Already tracking\\n\");)\n+\t\tmono_mutex_unlock (&coverage_mutex);\n+\t\treturn TRUE;\n+\t}\n+\n+\tklass = mono_method_get_class (method);\n+\timage = mono_class_get_image (klass);\n+\n+\t// Don't handle coverage for the core assemblies\n+\tif (g_hash_table_lookup (suppressed_assemblies, mono_image_get_name (image)) != NULL) {\n+\t\tmono_mutex_unlock (&coverage_mutex);\n+\t\treturn FALSE;\n+\t}\n+\n+\tif (prof->coverage_filters) {\n+\t\t/* Check already filtered classes first */\n+\t\tif (g_hash_table_lookup (filtered_classes, klass)) {\n+\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"   Already filtered\\n\");)\n+\t\t\tmono_mutex_unlock (&coverage_mutex);\n+\t\t\treturn FALSE;\n+\t\t}\n+\n+\t\tclassname = mono_type_get_name (mono_class_get_type (klass));\n+\n+\t\tfqn = g_strdup_printf (\"[%s]%s\", mono_image_get_name (image), classname);\n+\n+\t\tCOVERAGE_DEBUG(fprintf (stderr, \"   Looking for %s in filter\\n\", fqn);)\n+\t\t// Check positive filters first\n+\t\thas_positive = FALSE;\n+\t\tfound = FALSE;\n+\t\tfor (guint i = 0; i < prof->coverage_filters->len; ++i) {\n+\t\t\tchar *filter = g_ptr_array_index (prof->coverage_filters, i);\n+\t\t\tif (filter [0] == '+') {\n+\t\t\t\tfilter = &filter [1];\n+\t\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"   Checking against +%s ...\", filter);)\n+\t\t\t\tif (strstr (fqn, filter) != NULL) {\n+\t\t\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"matched\\n\");)\n+\t\t\t\t\tfound = TRUE;\n+\t\t\t\t} else {\n+\t\t\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"no match\\n\");)\n+\t\t\t\t}\n+\t\t\t\thas_positive = TRUE;\n+\t\t\t}\n+\t\t}\n+\t\tif (has_positive && !found) {\n+\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"   Positive match was not found\\n\");)\n+\t\t\tg_hash_table_insert (filtered_classes, klass, klass);\n+\t\t\tmono_mutex_unlock (&coverage_mutex);\n+\t\t\tg_free (fqn);\n+\t\t\tg_free (classname);\n+\t\t\treturn FALSE;\n+\t\t}\n+\n+\t\tfor (guint i = 0; i < prof->coverage_filters->len; ++i) {\n+\t\t\t// Is substring search suffices ???\n+\t\t\tchar *filter = g_ptr_array_index (prof->coverage_filters, i);\n+\t\t\tif (filter [0] == '+')\n+\t\t\t\tcontinue;\n+\n+\t\t\t// Skip '-'\n+\t\t\tfilter = &filter [1];\n+\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"   Checking against -%s ...\", filter);)\n+\t\t\tif (strstr (fqn, filter) != NULL) {\n+\t\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"matched\\n\");)\n+\t\t\t\tg_hash_table_insert (filtered_classes, klass, klass);\n+\t\t\t\tmono_mutex_unlock (&coverage_mutex);\n+\t\t\t\tg_free (fqn);\n+\t\t\t\tg_free (classname);\n+\t\t\t\treturn FALSE;\n+\t\t\t} else {\n+\t\t\t\tCOVERAGE_DEBUG(fprintf (stderr, \"no match\\n\");)\n+\t\t\t}\n+\t\t}\n+\t\tg_free (fqn);\n+\t\tg_free (classname);\n+\t}\n+\n+\tCOVERAGE_DEBUG(fprintf (stderr, \"   Handling coverage for %s\\n\", mono_method_get_name (method));)\n+\theader = mono_method_get_header (method);\n+\n+\tmono_method_header_get_code (header, &code_size, NULL);\n+\tif (code_size > 20000) {\n+\t\tg_warning (\"Unable to instrument method %s:%s since it is too complex.\", mono_class_get_name (klass), mono_method_get_name (method));","path":"mono/profiler/proflog.c","position":539,"original_position":539,"commit_id":"334325381311c93ced87128f1ecf307eadda90a9","original_commit_id":"334325381311c93ced87128f1ecf307eadda90a9","user":{"login":"alexrp","id":44076,"avatar_url":"https://avatars.githubusercontent.com/u/44076?v=3","gravatar_id":"","url":"https://api.github.com/users/alexrp","html_url":"https://github.com/alexrp","followers_url":"https://api.github.com/users/alexrp/followers","following_url":"https://api.github.com/users/alexrp/following{/other_user}","gists_url":"https://api.github.com/users/alexrp/gists{/gist_id}","starred_url":"https://api.github.com/users/alexrp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexrp/subscriptions","organizations_url":"https://api.github.com/users/alexrp/orgs","repos_url":"https://api.github.com/users/alexrp/repos","events_url":"https://api.github.com/users/alexrp/events{/privacy}","received_events_url":"https://api.github.com/users/alexrp/received_events","type":"User","site_admin":false},"body":"why do we do this?","created_at":"2015-04-07T04:36:19Z","updated_at":"2015-04-07T04:36:19Z","html_url":"https://github.com/mono/mono/pull/1626#discussion_r27851097","pull_request_url":"https://api.github.com/repos/mono/mono/pulls/1626","_links":{"self":{"href":"https://api.github.com/repos/mono/mono/pulls/comments/27851097"},"html":{"href":"https://github.com/mono/mono/pull/1626#discussion_r27851097"},"pull_request":{"href":"https://api.github.com/repos/mono/mono/pulls/1626"}}},"pull_request":{"url":"https://api.github.com/repos/mono/mono/pulls/1626","id":31113146,"html_url":"https://github.com/mono/mono/pull/1626","diff_url":"https://github.com/mono/mono/pull/1626.diff","patch_url":"https://github.com/mono/mono/pull/1626.patch","issue_url":"https://api.github.com/repos/mono/mono/issues/1626","number":1626,"state":"open","locked":false,"title":"Add coverage to log profiler","user":{"login":"iainx","id":1253364,"avatar_url":"https://avatars.githubusercontent.com/u/1253364?v=3","gravatar_id":"","url":"https://api.github.com/users/iainx","html_url":"https://github.com/iainx","followers_url":"https://api.github.com/users/iainx/followers","following_url":"https://api.github.com/users/iainx/following{/other_user}","gists_url":"https://api.github.com/users/iainx/gists{/gist_id}","starred_url":"https://api.github.com/users/iainx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iainx/subscriptions","organizations_url":"https://api.github.com/users/iainx/orgs","repos_url":"https://api.github.com/users/iainx/repos","events_url":"https://api.github.com/users/iainx/events{/privacy}","received_events_url":"https://api.github.com/users/iainx/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-03-13T10:08:54Z","updated_at":"2015-04-07T04:36:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"196a82fa14e7053596843089d2f8eca6ef2a02e3","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mono/mono/pulls/1626/commits","review_comments_url":"https://api.github.com/repos/mono/mono/pulls/1626/comments","review_comment_url":"https://api.github.com/repos/mono/mono/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mono/mono/issues/1626/comments","statuses_url":"https://api.github.com/repos/mono/mono/statuses/334325381311c93ced87128f1ecf307eadda90a9","head":{"label":"iainx:add-coverage-to-log-profiler","ref":"add-coverage-to-log-profiler","sha":"334325381311c93ced87128f1ecf307eadda90a9","user":{"login":"iainx","id":1253364,"avatar_url":"https://avatars.githubusercontent.com/u/1253364?v=3","gravatar_id":"","url":"https://api.github.com/users/iainx","html_url":"https://github.com/iainx","followers_url":"https://api.github.com/users/iainx/followers","following_url":"https://api.github.com/users/iainx/following{/other_user}","gists_url":"https://api.github.com/users/iainx/gists{/gist_id}","starred_url":"https://api.github.com/users/iainx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iainx/subscriptions","organizations_url":"https://api.github.com/users/iainx/orgs","repos_url":"https://api.github.com/users/iainx/repos","events_url":"https://api.github.com/users/iainx/events{/privacy}","received_events_url":"https://api.github.com/users/iainx/received_events","type":"User","site_admin":false},"repo":{"id":31374484,"name":"mono","full_name":"iainx/mono","owner":{"login":"iainx","id":1253364,"avatar_url":"https://avatars.githubusercontent.com/u/1253364?v=3","gravatar_id":"","url":"https://api.github.com/users/iainx","html_url":"https://github.com/iainx","followers_url":"https://api.github.com/users/iainx/followers","following_url":"https://api.github.com/users/iainx/following{/other_user}","gists_url":"https://api.github.com/users/iainx/gists{/gist_id}","starred_url":"https://api.github.com/users/iainx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iainx/subscriptions","organizations_url":"https://api.github.com/users/iainx/orgs","repos_url":"https://api.github.com/users/iainx/repos","events_url":"https://api.github.com/users/iainx/events{/privacy}","received_events_url":"https://api.github.com/users/iainx/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/iainx/mono","description":"Mono open source ECMA CLI, C# and .NET implementation.","fork":true,"url":"https://api.github.com/repos/iainx/mono","forks_url":"https://api.github.com/repos/iainx/mono/forks","keys_url":"https://api.github.com/repos/iainx/mono/keys{/key_id}","collaborators_url":"https://api.github.com/repos/iainx/mono/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/iainx/mono/teams","hooks_url":"https://api.github.com/repos/iainx/mono/hooks","issue_events_url":"https://api.github.com/repos/iainx/mono/issues/events{/number}","events_url":"https://api.github.com/repos/iainx/mono/events","assignees_url":"https://api.github.com/repos/iainx/mono/assignees{/user}","branches_url":"https://api.github.com/repos/iainx/mono/branches{/branch}","tags_url":"https://api.github.com/repos/iainx/mono/tags","blobs_url":"https://api.github.com/repos/iainx/mono/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/iainx/mono/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/iainx/mono/git/refs{/sha}","trees_url":"https://api.github.com/repos/iainx/mono/git/trees{/sha}","statuses_url":"https://api.github.com/repos/iainx/mono/statuses/{sha}","languages_url":"https://api.github.com/repos/iainx/mono/languages","stargazers_url":"https://api.github.com/repos/iainx/mono/stargazers","contributors_url":"https://api.github.com/repos/iainx/mono/contributors","subscribers_url":"https://api.github.com/repos/iainx/mono/subscribers","subscription_url":"https://api.github.com/repos/iainx/mono/subscription","commits_url":"https://api.github.com/repos/iainx/mono/commits{/sha}","git_commits_url":"https://api.github.com/repos/iainx/mono/git/commits{/sha}","comments_url":"https://api.github.com/repos/iainx/mono/comments{/number}","issue_comment_url":"https://api.github.com/repos/iainx/mono/issues/comments{/number}","contents_url":"https://api.github.com/repos/iainx/mono/contents/{+path}","compare_url":"https://api.github.com/repos/iainx/mono/compare/{base}...{head}","merges_url":"https://api.github.com/repos/iainx/mono/merges","archive_url":"https://api.github.com/repos/iainx/mono/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/iainx/mono/downloads","issues_url":"https://api.github.com/repos/iainx/mono/issues{/number}","pulls_url":"https://api.github.com/repos/iainx/mono/pulls{/number}","milestones_url":"https://api.github.com/repos/iainx/mono/milestones{/number}","notifications_url":"https://api.github.com/repos/iainx/mono/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/iainx/mono/labels{/name}","releases_url":"https://api.github.com/repos/iainx/mono/releases{/id}","created_at":"2015-02-26T15:47:15Z","updated_at":"2015-04-01T18:37:11Z","pushed_at":"2015-04-01T20:31:38Z","git_url":"git://github.com/iainx/mono.git","ssh_url":"git@github.com:iainx/mono.git","clone_url":"https://github.com/iainx/mono.git","svn_url":"https://github.com/iainx/mono","homepage":"http://www.mono-project.com/","size":396309,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mono:master","ref":"master","sha":"03b7f17ecd0236e35b78aec68d9220a7f7b51c9a","user":{"login":"mono","id":53395,"avatar_url":"https://avatars.githubusercontent.com/u/53395?v=3","gravatar_id":"","url":"https://api.github.com/users/mono","html_url":"https://github.com/mono","followers_url":"https://api.github.com/users/mono/followers","following_url":"https://api.github.com/users/mono/following{/other_user}","gists_url":"https://api.github.com/users/mono/gists{/gist_id}","starred_url":"https://api.github.com/users/mono/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mono/subscriptions","organizations_url":"https://api.github.com/users/mono/orgs","repos_url":"https://api.github.com/users/mono/repos","events_url":"https://api.github.com/users/mono/events{/privacy}","received_events_url":"https://api.github.com/users/mono/received_events","type":"Organization","site_admin":false},"repo":{"id":791611,"name":"mono","full_name":"mono/mono","owner":{"login":"mono","id":53395,"avatar_url":"https://avatars.githubusercontent.com/u/53395?v=3","gravatar_id":"","url":"https://api.github.com/users/mono","html_url":"https://github.com/mono","followers_url":"https://api.github.com/users/mono/followers","following_url":"https://api.github.com/users/mono/following{/other_user}","gists_url":"https://api.github.com/users/mono/gists{/gist_id}","starred_url":"https://api.github.com/users/mono/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mono/subscriptions","organizations_url":"https://api.github.com/users/mono/orgs","repos_url":"https://api.github.com/users/mono/repos","events_url":"https://api.github.com/users/mono/events{/privacy}","received_events_url":"https://api.github.com/users/mono/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mono/mono","description":"Mono open source ECMA CLI, C# and .NET implementation.","fork":false,"url":"https://api.github.com/repos/mono/mono","forks_url":"https://api.github.com/repos/mono/mono/forks","keys_url":"https://api.github.com/repos/mono/mono/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mono/mono/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mono/mono/teams","hooks_url":"https://api.github.com/repos/mono/mono/hooks","issue_events_url":"https://api.github.com/repos/mono/mono/issues/events{/number}","events_url":"https://api.github.com/repos/mono/mono/events","assignees_url":"https://api.github.com/repos/mono/mono/assignees{/user}","branches_url":"https://api.github.com/repos/mono/mono/branches{/branch}","tags_url":"https://api.github.com/repos/mono/mono/tags","blobs_url":"https://api.github.com/repos/mono/mono/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mono/mono/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mono/mono/git/refs{/sha}","trees_url":"https://api.github.com/repos/mono/mono/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mono/mono/statuses/{sha}","languages_url":"https://api.github.com/repos/mono/mono/languages","stargazers_url":"https://api.github.com/repos/mono/mono/stargazers","contributors_url":"https://api.github.com/repos/mono/mono/contributors","subscribers_url":"https://api.github.com/repos/mono/mono/subscribers","subscription_url":"https://api.github.com/repos/mono/mono/subscription","commits_url":"https://api.github.com/repos/mono/mono/commits{/sha}","git_commits_url":"https://api.github.com/repos/mono/mono/git/commits{/sha}","comments_url":"https://api.github.com/repos/mono/mono/comments{/number}","issue_comment_url":"https://api.github.com/repos/mono/mono/issues/comments{/number}","contents_url":"https://api.github.com/repos/mono/mono/contents/{+path}","compare_url":"https://api.github.com/repos/mono/mono/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mono/mono/merges","archive_url":"https://api.github.com/repos/mono/mono/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mono/mono/downloads","issues_url":"https://api.github.com/repos/mono/mono/issues{/number}","pulls_url":"https://api.github.com/repos/mono/mono/pulls{/number}","milestones_url":"https://api.github.com/repos/mono/mono/milestones{/number}","notifications_url":"https://api.github.com/repos/mono/mono/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mono/mono/labels{/name}","releases_url":"https://api.github.com/repos/mono/mono/releases{/id}","created_at":"2010-07-22T18:06:36Z","updated_at":"2015-04-07T04:22:20Z","pushed_at":"2015-04-07T04:22:19Z","git_url":"git://github.com/mono/mono.git","ssh_url":"git@github.com:mono/mono.git","clone_url":"https://github.com/mono/mono.git","svn_url":"https://github.com/mono/mono","homepage":"http://www.mono-project.com/","size":1330749,"stargazers_count":3250,"watchers_count":3250,"language":"C#","has_issues":false,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":1619,"mirror_url":null,"open_issues_count":95,"forks":1619,"open_issues":95,"watchers":3250,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mono/mono/pulls/1626"},"html":{"href":"https://github.com/mono/mono/pull/1626"},"issue":{"href":"https://api.github.com/repos/mono/mono/issues/1626"},"comments":{"href":"https://api.github.com/repos/mono/mono/issues/1626/comments"},"review_comments":{"href":"https://api.github.com/repos/mono/mono/pulls/1626/comments"},"review_comment":{"href":"https://api.github.com/repos/mono/mono/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mono/mono/pulls/1626/commits"},"statuses":{"href":"https://api.github.com/repos/mono/mono/statuses/334325381311c93ced87128f1ecf307eadda90a9"}}}}