diff --git a/.travis.yml b/.travis.yml index f2e77cd1..1f9c7a3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ osx_image: xcode9.2 before_install: - curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem - - gem install bundler --no-ri --no-rdoc + - gem install bundler -v "~> 1.0" --no-ri --no-rdoc install: - bundle install --without=documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fdfd9a2..68f1f4cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ # CHANGELOG -## master +## v2.4.7 + +* Update dependencies + [dnedrow](https://github.com/dnedrow) + +* Fixed errors when llvm-cov argument length exceeds ARG_MAX + [weibel](https://github.com/weibel) + [#414](https://github.com/SlatherOrg/slather/pull/414) + +* Show "No coverage directory found." instead of "implicit conversion nil into String" + [phimage](https://github.com/phimage) + [#381](https://github.com/SlatherOrg/slather/pull/381) [#341](https://github.com/SlatherOrg/slather/issues/341) + +## v2.4.6 * Fix .dSYM and .swiftmodule files filtering in find_binary_files() [krin-san](https://github.com/krin-san) @@ -8,7 +21,11 @@ * Fixed loading coverage for a single source file [blackm00n](https://github.com/blackm00n) - [#377](https://github.com/SlatherOrg/slather/pull/377) + [#377](https://github.com/SlatherOrg/slather/pull/377) [#398](https://github.com/SlatherOrg/slather/pull/398) + +* Fixed truncated file list in HTML export + [miroslavkovac](https://github.com/miroslavkovac) + [#402](https://github.com/SlatherOrg/slather/pull/402) [#261](https://github.com/SlatherOrg/slather/issues/261) ## v2.4.5 diff --git a/README_Images/test_scheme.png b/README_Images/test_scheme.png index 550ec4d2..f0572654 100644 Binary files a/README_Images/test_scheme.png and b/README_Images/test_scheme.png differ diff --git a/assets/list.min.js b/assets/list.min.js index 56c17e39..8327aaf1 100644 --- a/assets/list.min.js +++ b/assets/list.min.js @@ -1 +1 @@ -!function(){function a(b,c,d){var e=a.resolve(b);if(null==e){d=d||b,c=c||"root";var f=new Error('Failed to require "'+d+'" from "'+c+'"');throw f.path=d,f.parent=c,f.require=!0,f}var g=a.modules[e];if(!g._resolving&&!g.exports){var h={};h.exports={},h.client=h.component=!0,g._resolving=!0,g.call(this,h.exports,a.relative(e),h),delete g._resolving,g.exports=h.exports}return g.exports}a.modules={},a.aliases={},a.resolve=function(b){"/"===b.charAt(0)&&(b=b.slice(1));for(var c=[b,b+".js",b+".json",b+"/index.js",b+"/index.json"],d=0;di;i++)if(h.test(f[i].className)){if(c)return f[i];d[j]=f[i],j++}return d}}()}),a.register("javve-get-attribute/index.js",function(a,b,c){c.exports=function(a,b){var c=a.getAttribute&&a.getAttribute(b)||null;if(!c)for(var d=a.attributes,e=d.length,f=0;e>f;f++)void 0!==b[f]&&b[f].nodeName===b&&(c=b[f].nodeValue);return c}}),a.register("javve-natural-sort/index.js",function(a,b,c){c.exports=function(a,b,c){var d,e,f=/(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,g=/(^[ ]*|[ ]*$)/g,h=/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,i=/^0x[0-9a-f]+$/i,j=/^0/,c=c||{},k=function(a){return c.insensitive&&(""+a).toLowerCase()||""+a},l=k(a).replace(g,"")||"",m=k(b).replace(g,"")||"",n=l.replace(f,"\x00$1\x00").replace(/\0$/,"").replace(/^\0/,"").split("\x00"),o=m.replace(f,"\x00$1\x00").replace(/\0$/,"").replace(/^\0/,"").split("\x00"),p=parseInt(l.match(i))||1!=n.length&&l.match(h)&&Date.parse(l),q=parseInt(m.match(i))||p&&m.match(h)&&Date.parse(m)||null,r=c.desc?-1:1;if(q){if(q>p)return-1*r;if(p>q)return 1*r}for(var s=0,t=Math.max(n.length,o.length);t>s;s++){if(d=!(n[s]||"").match(j)&&parseFloat(n[s])||n[s]||0,e=!(o[s]||"").match(j)&&parseFloat(o[s])||o[s]||0,isNaN(d)!==isNaN(e))return isNaN(d)?1:-1;if(typeof d!=typeof e&&(d+="",e+=""),e>d)return-1*r;if(d>e)return 1*r}return 0}}),a.register("javve-to-string/index.js",function(a,b,c){c.exports=function(a){return a=void 0===a?"":a,a=null===a?"":a,a=a.toString()}}),a.register("component-type/index.js",function(a,b,c){var d=Object.prototype.toString;c.exports=function(a){switch(d.call(a)){case"[object Date]":return"date";case"[object RegExp]":return"regexp";case"[object Arguments]":return"arguments";case"[object Array]":return"array";case"[object Error]":return"error"}return null===a?"null":void 0===a?"undefined":a!==a?"nan":a&&1===a.nodeType?"element":typeof a.valueOf()}}),a.register("list.js/index.js",function(a,b,c){!function(a,d){"use strict";var e=a.document,f=b("get-by-class"),g=b("extend"),h=b("indexof"),i=function(a,c,i){var j,k=this,l=b("./src/item")(k),m=b("./src/add-async")(k),n=b("./src/parse")(k);j={start:function(){k.listClass="list",k.searchClass="search",k.sortClass="sort",k.page=200,k.i=1,k.items=[],k.visibleItems=[],k.matchingItems=[],k.searched=!1,k.filtered=!1,k.handlers={updated:[]},k.plugins={},k.helpers={getByClass:f,extend:g,indexOf:h},g(k,c),k.listContainer="string"==typeof a?e.getElementById(a):a,k.listContainer&&(k.list=f(k.listContainer,k.listClass,!0),k.templater=b("./src/templater")(k),k.search=b("./src/search")(k),k.filter=b("./src/filter")(k),k.sort=b("./src/sort")(k),this.items(),k.update(),this.plugins())},items:function(){n(k.list),i!==d&&k.add(i)},plugins:function(){for(var a=0;af;f++){var h=null;a[f]instanceof l?(h=a[f],h.reload()):(e=k.items.length>k.page?!0:!1,h=new l(a[f],d,e)),k.items.push(h),c.push(h)}return k.update(),c},this.show=function(a,b){return this.i=a,this.page=b,k.update(),k},this.remove=function(a,b,c){for(var d=0,e=0,f=k.items.length;f>e;e++)k.items[e].values()[a]==b&&(k.templater.remove(k.items[e],c),k.items.splice(e,1),f--,e--,d++);return k.update(),d},this.get=function(a,b){for(var c=[],d=0,e=k.items.length;e>d;d++){var f=k.items[d];f.values()[a]==b&&c.push(f)}return c},this.size=function(){return k.items.length},this.clear=function(){return k.templater.clear(),k.items=[],k},this.on=function(a,b){return k.handlers[a].push(b),k},this.off=function(a,b){var c=k.handlers[a],d=h(c,b);return d>-1&&c.splice(d,1),k},this.trigger=function(a){for(var b=k.handlers[a].length;b--;)k.handlers[a][b](k);return k},this.reset={filter:function(){for(var a=k.items,b=a.length;b--;)a[b].filtered=!1;return k},search:function(){for(var a=k.items,b=a.length;b--;)a[b].found=!1;return k}},this.update=function(){var a=k.items,b=a.length;k.visibleItems=[],k.matchingItems=[],k.templater.clear();for(var c=0;b>c;c++)a[c].matching()&&k.matchingItems.length+1>=k.i&&k.visibleItems.lengthb;b++)j.item(a.items[b])},item:function(a){a.found=!1;for(var b=0,d=c.length;d>b;b++)if(j.values(a.values(),c[b]))return a.found=!0,void 0},values:function(a,c){return a.hasOwnProperty(c)&&(b=f(a[c]).toLowerCase(),""!==g&&b.search(g)>-1)?!0:!1},reset:function(){a.reset.search(),a.searched=!1}},k=function(b){return a.trigger("searchStart"),i.resetList(),i.setSearchString(b),i.setOptions(arguments),i.setColumns(),""===g?j.reset():(a.searched=!0,h?h(g,c):j.list()),a.update(),a.trigger("searchComplete"),a.visibleItems};return a.handlers.searchStart=a.handlers.searchStart||[],a.handlers.searchComplete=a.handlers.searchComplete||[],d.bind(e(a.listContainer,a.searchClass),"keyup",function(b){var c=b.target||b.srcElement,d=""===c.value&&!a.searched;d||k(c.value)}),d.bind(e(a.listContainer,a.searchClass),"input",function(a){var b=a.target||a.srcElement;""===b.value&&k("")}),a.helpers.toString=f,k}}),a.register("list.js/src/sort.js",function(a,b,c){var d=b("natural-sort"),e=b("classes"),f=b("events"),g=b("get-by-class"),h=b("get-attribute");c.exports=function(a){a.sortFunction=a.sortFunction||function(a,b,c){return c.desc="desc"==c.order?!0:!1,d(a.values()[c.valueName],b.values()[c.valueName],c)};var b={els:void 0,clear:function(){for(var a=0,c=b.els.length;c>a;a++)e(b.els[a]).remove("asc"),e(b.els[a]).remove("desc")},getOrder:function(a){var b=h(a,"data-order");return"asc"==b||"desc"==b?b:e(a).has("desc")?"asc":e(a).has("asc")?"desc":"asc"},getInSensitive:function(a,b){var c=h(a,"data-insensitive");b.insensitive="true"===c?!0:!1},setOrder:function(a){for(var c=0,d=b.els.length;d>c;c++){var f=b.els[c];if(h(f,"data-sort")===a.valueName){var g=h(f,"data-order");"asc"==g||"desc"==g?g==a.order&&e(f).add(a.order):e(f).add(a.order)}}}},c=function(){a.trigger("sortStart"),options={};var c=arguments[0].currentTarget||arguments[0].srcElement||void 0;c?(options.valueName=h(c,"data-sort"),b.getInSensitive(c,options),options.order=b.getOrder(c)):(options=arguments[1]||options,options.valueName=arguments[0],options.order=options.order||"asc",options.insensitive="undefined"==typeof options.insensitive?!0:options.insensitive),b.clear(),b.setOrder(options),options.sortFunction=options.sortFunction||a.sortFunction,a.items.sort(function(a,b){return options.sortFunction(a,b,options)}),a.update(),a.trigger("sortComplete")};return a.handlers.sortStart=a.handlers.sortStart||[],a.handlers.sortComplete=a.handlers.sortComplete||[],b.els=g(a.listContainer,a.sortClass),f.bind(b.els,"click",c),a.on("searchStart",b.clear),a.on("filterStart",b.clear),a.helpers.classes=e,a.helpers.naturalSort=d,a.helpers.events=f,a.helpers.getAttribute=h,c}}),a.register("list.js/src/item.js",function(a,b,c){c.exports=function(a){return function(b,c,d){var e=this;this._values={},this.found=!1,this.filtered=!1;var f=function(b,c,d){if(void 0===c)d?e.values(b,d):e.values(b);else{e.elm=c;var f=a.templater.get(e,b);e.values(f)}};this.values=function(b,c){if(void 0===b)return e._values;for(var d in b)e._values[d]=b[d];c!==!0&&a.templater.set(e,e.values())},this.show=function(){a.templater.show(e)},this.hide=function(){a.templater.hide(e)},this.matching=function(){return a.filtered&&a.searched&&e.found&&e.filtered||a.filtered&&!a.searched&&e.filtered||!a.filtered&&a.searched&&e.found||!a.filtered&&!a.searched},this.visible=function(){return e.elm.parentNode==a.list?!0:!1},f(b,c,d)}}}),a.register("list.js/src/templater.js",function(a,b,c){var d=b("get-by-class"),e=function(a){function b(b){if(void 0===b){for(var c=a.list.childNodes,d=0,e=c.length;e>d;d++)if(void 0===c[d].data)return c[d];return null}if(-1!==b.indexOf("<")){var f=document.createElement("div");return f.innerHTML=b,f.firstChild}return document.getElementById(a.item)}var c=b(a.item),e=this;this.get=function(a,b){e.create(a);for(var c={},f=0,g=b.length;g>f;f++){var h=d(a.elm,b[f],!0);c[b[f]]=h?h.innerHTML:""}return c},this.set=function(a,b){if(!e.create(a))for(var c in b)if(b.hasOwnProperty(c)){var f=d(a.elm,c,!0);f&&("IMG"===f.tagName&&""!==b[c]?f.src=b[c]:f.innerHTML=b[c])}},this.create=function(a){if(void 0!==a.elm)return!1;var b=c.cloneNode(!0);return b.removeAttribute("id"),a.elm=b,e.set(a,a.values()),!0},this.remove=function(b){a.list.removeChild(b.elm)},this.show=function(b){e.create(b),a.list.appendChild(b.elm)},this.hide=function(b){void 0!==b.elm&&b.elm.parentNode===a.list&&a.list.removeChild(b.elm)},this.clear=function(){if(a.list.hasChildNodes())for(;a.list.childNodes.length>=1;)a.list.removeChild(a.list.firstChild)}};c.exports=function(a){return new e(a)}}),a.register("list.js/src/filter.js",function(a,b,c){c.exports=function(a){return a.handlers.filterStart=a.handlers.filterStart||[],a.handlers.filterComplete=a.handlers.filterComplete||[],function(b){if(a.trigger("filterStart"),a.i=1,a.reset.filter(),void 0===b)a.filtered=!1;else{a.filtered=!0;for(var c=a.items,d=0,e=c.length;e>d;d++){var f=c[d];f.filtered=b(f)?!0:!1}}return a.update(),a.trigger("filterComplete"),a.visibleItems}}}),a.register("list.js/src/add-async.js",function(a,b,c){c.exports=function(a){return function(b,c,d){var e=b.splice(0,100);d=d||[],d=d.concat(a.add(e)),b.length>0?setTimeout(function(){addAsync(b,c,d)},10):(a.update(),c(d))}}}),a.register("list.js/src/parse.js",function(a,b,c){c.exports=function(a){var c=b("./item")(a),d=function(a){for(var b=a.childNodes,c=[],d=0,e=b.length;e>d;d++)void 0===b[d].data&&c.push(b[d]);return c},e=function(b,d){for(var e=0,f=b.length;f>e;e++)a.items.push(new c(d,b[e]))},f=function(b,c){var d=b.splice(0,100);e(d,c),b.length>0?setTimeout(function(){init.items.indexAsync(b,c)},10):a.update()};return function(){var b=d(a.list),c=a.valueNames;a.indexAsync?f(b,c):e(b,c)}}}),a.alias("component-classes/index.js","list.js/deps/classes/index.js"),a.alias("component-classes/index.js","classes/index.js"),a.alias("component-indexof/index.js","component-classes/deps/indexof/index.js"),a.alias("segmentio-extend/index.js","list.js/deps/extend/index.js"),a.alias("segmentio-extend/index.js","extend/index.js"),a.alias("component-indexof/index.js","list.js/deps/indexof/index.js"),a.alias("component-indexof/index.js","indexof/index.js"),a.alias("javve-events/index.js","list.js/deps/events/index.js"),a.alias("javve-events/index.js","events/index.js"),a.alias("component-event/index.js","javve-events/deps/event/index.js"),a.alias("timoxley-to-array/index.js","javve-events/deps/to-array/index.js"),a.alias("javve-get-by-class/index.js","list.js/deps/get-by-class/index.js"),a.alias("javve-get-by-class/index.js","get-by-class/index.js"),a.alias("javve-get-attribute/index.js","list.js/deps/get-attribute/index.js"),a.alias("javve-get-attribute/index.js","get-attribute/index.js"),a.alias("javve-natural-sort/index.js","list.js/deps/natural-sort/index.js"),a.alias("javve-natural-sort/index.js","natural-sort/index.js"),a.alias("javve-to-string/index.js","list.js/deps/to-string/index.js"),a.alias("javve-to-string/index.js","list.js/deps/to-string/index.js"),a.alias("javve-to-string/index.js","to-string/index.js"),a.alias("javve-to-string/index.js","javve-to-string/index.js"),a.alias("component-type/index.js","list.js/deps/type/index.js"),a.alias("component-type/index.js","type/index.js"),"object"==typeof exports?module.exports=a("list.js"):"function"==typeof define&&define.amd?define(function(){return a("list.js")}):this.List=a("list.js")}(); \ No newline at end of file +var List=function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=11)}([function(t,e,r){function n(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}var i=r(4),s=/\s+/;Object.prototype.toString;t.exports=function(t){return new n(t)},n.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array(),r=i(e,t);return~r||e.push(t),this.el.className=e.join(" "),this},n.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=i(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},n.prototype.toggle=function(t,e){return this.list?("undefined"!=typeof e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):("undefined"!=typeof e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},n.prototype.array=function(){var t=this.el.getAttribute("class")||"",e=t.replace(/^\s+|\s+$/g,""),r=e.split(s);return""===r[0]&&r.shift(),r},n.prototype.has=n.prototype.contains=function(t){return this.list?this.list.contains(t):!!~i(this.array(),t)}},function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",i=window.removeEventListener?"removeEventListener":"detachEvent",s="addEventListener"!==n?"on":"",a=r(5);e.bind=function(t,e,r,i){t=a(t);for(var o=0;o0?setTimeout(function(){e(r,n,i)},1):(t.update(),n(i))};return e}},function(t,e){t.exports=function(t){return t.handlers.filterStart=t.handlers.filterStart||[],t.handlers.filterComplete=t.handlers.filterComplete||[],function(e){if(t.trigger("filterStart"),t.i=1,t.reset.filter(),void 0===e)t.filtered=!1;else{t.filtered=!0;for(var r=t.items,n=0,i=r.length;nv.page,a=new m(t[i],void 0,n),v.items.push(a),r.push(a)}return v.update(),r}},this.show=function(t,e){return this.i=t,this.page=e,v.update(),v},this.remove=function(t,e,r){for(var n=0,i=0,s=v.items.length;i-1&&r.splice(n,1),v},this.trigger=function(t){for(var e=v.handlers[t].length;e--;)v.handlers[t][e](v);return v},this.reset={filter:function(){for(var t=v.items,e=t.length;e--;)t[e].filtered=!1;return v},search:function(){for(var t=v.items,e=t.length;e--;)t[e].found=!1;return v}},this.update=function(){var t=v.items,e=t.length;v.visibleItems=[],v.matchingItems=[],v.templater.clear();for(var r=0;r=v.i&&v.visibleItems.lengthe},innerWindow:function(t,e,r){return t>=e-r&&t<=e+r},dotted:function(t,e,r,n,i,s,a){return this.dottedLeft(t,e,r,n,i,s)||this.dottedRight(t,e,r,n,i,s,a)},dottedLeft:function(t,e,r,n,i,s){return e==r+1&&!this.innerWindow(e,i,s)&&!this.right(e,n)},dottedRight:function(t,e,r,n,i,s,a){return!t.items[a-1].values().dotted&&(e==n&&!this.innerWindow(e,i,s)&&!this.right(e,n))}},a=function(e,r,n){i.bind(e,"click",function(){t.show((r-1)*n+1,n)})};return function(r){var n=new s(t.listContainer.id,{listClass:r.paginationClass||"pagination",item:"
  • ",valueNames:["page","dotted"],searchClass:"pagination-search-that-is-not-supposed-to-exist",sortClass:"pagination-sort-that-is-not-supposed-to-exist"});t.on("updated",function(){e(n,r)}),e(n,r)}}},function(t,e,r){t.exports=function(t){var e=r(2)(t),n=function(t){for(var e=t.childNodes,r=[],n=0,i=e.length;n0?setTimeout(function(){s(e,r)},1):(t.update(),t.trigger("parseComplete"))};return t.handlers.parseComplete=t.handlers.parseComplete||[],function(){var e=n(t.list),r=t.valueNames;t.indexAsync?s(e,r):i(e,r)}}},function(t,e){t.exports=function(t){var e,r,n,i,s={resetList:function(){t.i=1,t.templater.clear(),i=void 0},setOptions:function(t){2==t.length&&t[1]instanceof Array?r=t[1]:2==t.length&&"function"==typeof t[1]?(r=void 0,i=t[1]):3==t.length?(r=t[1],i=t[2]):r=void 0},setColumns:function(){0!==t.items.length&&void 0===r&&(r=void 0===t.searchColumns?s.toArray(t.items[0].values()):t.searchColumns)},setSearchString:function(e){e=t.utils.toString(e).toLowerCase(),e=e.replace(/[-[\]{}()*+?.,\\^$|#]/g,"\\$&"),n=e},toArray:function(t){var e=[];for(var r in t)e.push(r);return e}},a={list:function(){for(var e=0,r=t.items.length;e-1))},reset:function(){t.reset.search(),t.searched=!1}},o=function(e){return t.trigger("searchStart"),s.resetList(),s.setSearchString(e),s.setOptions(arguments),s.setColumns(),""===n?a.reset():(t.searched=!0,i?i(n,r):a.list()),t.update(),t.trigger("searchComplete"),t.visibleItems};return t.handlers.searchStart=t.handlers.searchStart||[],t.handlers.searchComplete=t.handlers.searchComplete||[],t.utils.events.bind(t.utils.getByClass(t.listContainer,t.searchClass),"keyup",function(e){var r=e.target||e.srcElement,n=""===r.value&&!t.searched;n||o(r.value)}),t.utils.events.bind(t.utils.getByClass(t.listContainer,t.searchClass),"input",function(t){var e=t.target||t.srcElement;""===e.value&&o("")}),o}},function(t,e){t.exports=function(t){var e={els:void 0,clear:function(){for(var r=0,n=e.els.length;r]/g.exec(e)){var s=document.createElement("tbody");return s.innerHTML=e,s.firstChild}if(e.indexOf("<")!==-1){var a=document.createElement("div");return a.innerHTML=e,a.firstChild}var o=document.getElementById(t.item);if(o)return o}},this.get=function(e,n){r.create(e);for(var i={},s=0,a=n.length;s=1;)t.list.removeChild(t.list.firstChild)},n()};t.exports=function(t){return new r(t)}},function(t,e){t.exports=function(t,e){var r=t.getAttribute&&t.getAttribute(e)||null;if(!r)for(var n=t.attributes,i=n.length,s=0;s=48&&t<=57}function i(t,e){for(var r=(t+="").length,i=(e+="").length,s=0,l=0;s32)return!1;var o=i,l=function(){var t,r={};for(t=0;t=p;b--){var w=l[t.charAt(b-1)];if(0===g?y[b]=(y[b+1]<<1|1)&w:y[b]=(y[b+1]<<1|1)&w|((v[b+1]|v[b])<<1|1)|v[b+1],y[b]&f){var x=n(g,b-1);if(x<=u){if(u=x,c=b-1,!(c>o))break;p=Math.max(1,2*o-c)}}}if(n(g+1,o)>u)break;v=y}return!(c<0)}}]); \ No newline at end of file diff --git a/lib/slather/project.rb b/lib/slather/project.rb index bff0fe5a..c6391485 100755 --- a/lib/slather/project.rb +++ b/lib/slather/project.rb @@ -161,24 +161,11 @@ def xccov_coverage_files def profdata_coverage_files coverage_files = [] - source_files = find_source_files || [] - line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0') if self.binary_file self.binary_file.each do |binary_path| - files = profdata_llvm_cov_output(binary_path, source_files).split("\n\n") - - coverage_files.concat(files.map do |source| - coverage_file = coverage_file_class.new(self, source, line_numbers_first) - # If a single source file is used, the resulting output does not contain the file name. - coverage_file.source_file_pathname = source_files.first if source_files.count == 1 - !coverage_file.ignored? ? coverage_file : nil - end.compact) - - if !source_files.empty? - coverage_file_paths = coverage_files.map { |file| file.source_file_pathname }.to_set - source_files.select! { |path| !coverage_file_paths.include?(path) } - end + pathnames_per_binary = pathnames_per_binary(binary_path) + coverage_files.concat(create_coverage_files_for_binary(binary_path, pathnames_per_binary)) end end @@ -186,6 +173,55 @@ def profdata_coverage_files end private :profdata_coverage_files + def pathnames_per_binary(binary_path) + coverage_json_string = llvm_cov_export_output(binary_path) + coverage_json = JSON.parse(coverage_json_string) + coverage_json["data"].reduce([]) do |result, chunk| + result.concat(chunk["files"].map do |file| + Pathname(file["filename"]).realpath + end) + end + end + private :pathnames_per_binary + + def create_coverage_files_for_binary(binary_path, pathnames_per_binary) + coverage_files = [] + + begin + coverage_files.concat(create_coverage_files(binary_path, pathnames_per_binary)) + rescue Errno::E2BIG => e + # pathnames_per_binary is too big for the OS to handle so it's split in two halfs which are processed independently + if pathnames_per_binary.count > 1 + left, right = pathnames_per_binary.each_slice( (pathnames_per_binary.size/2.0).round ).to_a + coverage_files.concat(create_coverage_files_for_binary(binary_path, left)) + coverage_files.concat(create_coverage_files_for_binary(binary_path, right)) + else + # pathnames_per_binary contains one element which is too big for the OS to handle. + raise e, "#{e}. A path in your project is close to the E2BIG limit. https://github.com/SlatherOrg/slather/pull/414", e.backtrace + end + end + + coverage_files + end + private :create_coverage_files_for_binary + + def create_coverage_files(binary_path, pathnames) + line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0') + files = create_profdata(binary_path, pathnames) + files.map do |source| + coverage_file = coverage_file_class.new(self, source, line_numbers_first) + # If a single source file is used, the resulting output does not contain the file name. + coverage_file.source_file_pathname = pathnames.first if pathnames.count == 1 + !coverage_file.ignored? ? coverage_file : nil + end.compact + end + private :create_coverage_files + + def create_profdata(binary_path, pathnames) + profdata_llvm_cov_output(binary_path, pathnames).split("\n\n") + end + private :create_profdata + def remove_extension(path) path.split(".")[0..-2].join(".") end @@ -221,7 +257,7 @@ def profdata_coverage_dir coverage_files = Dir[File.join(build_directory, "../**/ProfileData/*/Coverage.profdata")] end - if coverage_files != nil + if coverage_files != nil && coverage_files.count != 0 dir = Pathname.new(coverage_files.first).parent() end end @@ -244,6 +280,30 @@ def profdata_file end private :profdata_file + def unsafe_llvm_cov_export_output(binary_path) + profdata_file_arg = profdata_file + if profdata_file_arg == nil + raise StandardError, "No Coverage.profdata files found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set." + end + + if binary_path == nil + raise StandardError, "No binary file found." + end + + llvm_cov_args = %W(export -instr-profile #{profdata_file_arg} #{binary_path}) + if self.arch + llvm_cov_args << "--arch" << self.arch + end + `xcrun llvm-cov #{llvm_cov_args.shelljoin}` + end + private :unsafe_llvm_cov_export_output + + def llvm_cov_export_output(binary_path) + output = unsafe_llvm_cov_export_output(binary_path) + output.valid_encoding? ? output : output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace) + end + private :llvm_cov_export_output + def unsafe_profdata_llvm_cov_output(binary_path, source_files) profdata_file_arg = profdata_file if profdata_file_arg == nil diff --git a/lib/slather/version.rb b/lib/slather/version.rb index 7b2828e4..1b02d87a 100644 --- a/lib/slather/version.rb +++ b/lib/slather/version.rb @@ -1,3 +1,3 @@ module Slather - VERSION = '2.4.6' unless defined?(Slather::VERSION) + VERSION = '2.4.7' unless defined?(Slather::VERSION) end diff --git a/slather.gemspec b/slather.gemspec index 1e26ddbd..af8eef0e 100644 --- a/slather.gemspec +++ b/slather.gemspec @@ -17,20 +17,20 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.add_development_dependency 'bundler', '~> 1.6' - spec.add_development_dependency 'coveralls' - spec.add_development_dependency 'simplecov' - spec.add_development_dependency 'rake', '~> 10.4' - spec.add_development_dependency 'rspec', '~> 3.4' - spec.add_development_dependency 'pry', '~> 0.9' - spec.add_development_dependency 'cocoapods', '~> 1.2' - spec.add_development_dependency 'json_spec', '~> 1.1.4' - spec.add_development_dependency 'equivalent-xml', '~> 0.5.1' + spec.add_development_dependency 'bundler', '~> 1.17' + spec.add_development_dependency 'coveralls', '~> 0' + spec.add_development_dependency 'simplecov', '~> 0' + spec.add_development_dependency 'rake', '~> 12.3' + spec.add_development_dependency 'rspec', '~> 3.8' + spec.add_development_dependency 'pry', '~> 0.12' + spec.add_development_dependency 'cocoapods', '~> 1.5' + spec.add_development_dependency 'json_spec', '~> 1.1' + spec.add_development_dependency 'equivalent-xml', '~> 0.6' - spec.add_dependency 'clamp', '~> 0.6' - spec.add_dependency 'xcodeproj', '~> 1.4' - spec.add_dependency 'nokogiri', '~> 1.8.2' - spec.add_dependency 'CFPropertyList', '>= 2.2' + spec.add_dependency 'clamp', '~> 1.3' + spec.add_dependency 'xcodeproj', '~> 1.7' + spec.add_dependency 'nokogiri', '~> 1.8' + spec.add_dependency 'CFPropertyList', '>= 2.2', '< 4' - spec.add_runtime_dependency 'activesupport', '>= 4.0.2' + spec.add_runtime_dependency 'activesupport', '< 5', '>= 4.0.2' end diff --git a/spec/slather/coverage_service/coveralls_spec.rb b/spec/slather/coverage_service/coveralls_spec.rb index a297f0ee..8625082d 100644 --- a/spec/slather/coverage_service/coveralls_spec.rb +++ b/spec/slather/coverage_service/coveralls_spec.rb @@ -158,6 +158,15 @@ before(:each) { fixtures_project.ci_service = :travis_ci project_root = Pathname("./").realpath + allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(%q( + { + "data":[ + { + "files":[] + } + ] + } + )) allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return("#{project_root}/spec/fixtures/fixtures/fixtures.m: | 1|// | 2|// fixtures.m diff --git a/spec/slather/coverage_service/hardcover_spec.rb b/spec/slather/coverage_service/hardcover_spec.rb index 337d9fdb..ceed5cad 100644 --- a/spec/slather/coverage_service/hardcover_spec.rb +++ b/spec/slather/coverage_service/hardcover_spec.rb @@ -66,6 +66,15 @@ allow(Slather::Project).to receive(:yml).and_return(fixture_yaml) fixtures_project.ci_service = :jenkins_ci project_root = Pathname("./").realpath + allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(%q( + { + "data":[ + { + "files":[] + } + ] + } + )) allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return("#{project_root}/spec/fixtures/fixtures/fixtures.m: | 1|// | 2|// fixtures.m @@ -104,7 +113,6 @@ it "should always remove the hardcover_json_file after it's done" do allow(fixtures_project).to receive(:`) - allow(fixtures_project).to receive(:jenkins_job_id).and_return("slather-master/9182") allow(fixtures_project).to receive(:coverage_service_url).and_return("http://api.hardcover.io") fixtures_project.post diff --git a/spec/slather/project_spec.rb b/spec/slather/project_spec.rb index 44683434..85164e7f 100755 --- a/spec/slather/project_spec.rb +++ b/spec/slather/project_spec.rb @@ -64,15 +64,91 @@ class SpecCoverageFile < Slather::CoverageFile end end - describe "#profdata_coverage_files" do + describe "#profdata_coverage_files with large file lists" do class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile end + llvm_cov_export_output = %q( + { + "data":[ + { + "files":[ + { + "filename":"spec/fixtures/fixtures/Fixtures.swift" + } + ] + }, + { + "files":[ + { + "filename":"spec/fixtures/fixtures/Fixtures.swift" + } + ] + } + ] + }) + + profdata_llvm_cov_output = "#{FIXTURES_SWIFT_FILE_PATH}: + | 0| + | 1|import UIKit + | 2| + | 3|@UIApplicationMain + | 4|class AppDelegate: UIResponder, UIApplicationDelegate { + | 5| + | 6| var window: UIWindow? + | 7| + 1| 8| func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + 1| 9| return true + 1| 10| } + | 11| + 0| 12| func applicationWillResignActive(application: UIApplication) { + 0| 13| } + 0| 14|}" + before(:each) do allow(Dir).to receive(:[]).and_call_original allow(Dir).to receive(:[]).with("#{fixtures_project.build_directory}/**/Coverage.profdata").and_return(["/some/path/Coverage.profdata"]) allow(fixtures_project).to receive(:binary_file).and_return(["Fixtures"]) - allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return("#{FIXTURES_SWIFT_FILE_PATH}: + allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(llvm_cov_export_output) + allow(fixtures_project).to receive(:coverage_file_class).and_return(SpecXcode7CoverageFile) + allow(fixtures_project).to receive(:ignore_list).and_return([]) + end + + it "Should catch Errno::E2BIG and re-raise if the input is too large to split into multiple chunks" do + allow(fixtures_project).to receive(:unsafe_profdata_llvm_cov_output).and_raise(Errno::E2BIG) + expect { fixtures_project.send(:profdata_coverage_files) }.to raise_error(Errno::E2BIG, "Argument list too long. A path in your project is close to the E2BIG limit. https://github.com/SlatherOrg/slather/pull/414") + end + + it "Should catch Errno::E2BIG and return Coverage.profdata file objects when the work can be split into two" do + allow(fixtures_project).to receive(:unsafe_profdata_llvm_cov_output).once { + # raise once and then insert the stub + allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return(profdata_llvm_cov_output) + raise Errno::E2BIG + } + profdata_coverage_files = fixtures_project.send(:profdata_coverage_files) + profdata_coverage_files.each { |cf| expect(cf.kind_of?(SpecXcode7CoverageFile)).to be_truthy } + expect(profdata_coverage_files.map { |cf| cf.source_file_pathname.basename.to_s }).to eq(["Fixtures.swift", "Fixtures.swift"]) + end + end + + describe "#profdata_coverage_files" do + class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile + end + + llvm_cov_export_output = %q( + { + "data":[ + { + "files":[ + { + "filename":"spec/fixtures/fixtures/Fixtures.swift" + } + ] + } + ] + }) + + profdata_llvm_cov_output = "#{FIXTURES_SWIFT_FILE_PATH}: | 0| | 1|import UIKit | 2| @@ -87,7 +163,14 @@ class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile | 11| 0| 12| func applicationWillResignActive(application: UIApplication) { 0| 13| } - 0| 14|}") + 0| 14|}" + + before(:each) do + allow(Dir).to receive(:[]).and_call_original + allow(Dir).to receive(:[]).with("#{fixtures_project.build_directory}/**/Coverage.profdata").and_return(["/some/path/Coverage.profdata"]) + allow(fixtures_project).to receive(:binary_file).and_return(["Fixtures"]) + allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(llvm_cov_export_output) + allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return(profdata_llvm_cov_output) allow(fixtures_project).to receive(:coverage_file_class).and_return(SpecXcode7CoverageFile) allow(fixtures_project).to receive(:ignore_list).and_return([]) end @@ -111,6 +194,18 @@ class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile allow(fixtures_project).to receive(:ignore_list).and_return([]) allow(Dir).to receive(:[]).with("#{fixtures_project.build_directory}/**/Coverage.profdata").and_return(["/some/path/Coverage.profdata"]) allow(fixtures_project).to receive(:binary_file).and_return(["Fixtures"]) + allow(fixtures_project).to receive(:unsafe_llvm_cov_export_output).and_return(" + { + \"data\":[ + { + \"files\":[ + { + \"filename\":\"sp\145c/fixtures/fixtures/fixtures.m\" + } + ] + } + ] + }") allow(fixtures_project).to receive(:unsafe_profdata_llvm_cov_output).and_return("#{FIXTURES_SWIFT_FILE_PATH}: 1| 8| func application(application: \255, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 1| 9| return true @@ -563,6 +658,22 @@ class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile end it "should print out the coverage for each file, and then total coverage" do + allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(%q( + { + "data":[ + { + "files":[ + { + "filename":"spec/fixtures/fixtures/fixtures.m" + }, + { + "filename":"spec/fixtures/fixturesTwo/fixturesTwo.m" + } + ] + } + ] + } + )) ["spec/fixtures/fixtures/fixtures.m: 3 of 6 lines (50.00%)", "spec/fixtures/fixturesTwo/fixturesTwo.m: 6 of 6 lines (100.00%)", "Tested 9/12 statements",