git-object-browser 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. data/README.md +17 -0
  2. data/htdocs/{css → common/css}/angular-ui.min.css +0 -0
  3. data/htdocs/{css → common/css}/bootstrap-responsive.css +0 -0
  4. data/htdocs/{css → common/css}/bootstrap-responsive.min.css +0 -0
  5. data/htdocs/{css → common/css}/bootstrap.css +0 -0
  6. data/htdocs/{css → common/css}/bootstrap.min.css +0 -0
  7. data/htdocs/{css → common/css}/font-awesome-ie7.css +0 -0
  8. data/htdocs/{css → common/css}/font-awesome.css +0 -0
  9. data/htdocs/{css → common/css}/main.css +0 -0
  10. data/htdocs/{font → common/font}/fontawesome-webfont.eot +0 -0
  11. data/htdocs/{font → common/font}/fontawesome-webfont.svg +0 -0
  12. data/htdocs/{font → common/font}/fontawesome-webfont.ttf +0 -0
  13. data/htdocs/{font → common/font}/fontawesome-webfont.woff +0 -0
  14. data/htdocs/{img → common/img}/glyphicons-halflings-white.png +0 -0
  15. data/htdocs/{img → common/img}/glyphicons-halflings.png +0 -0
  16. data/htdocs/common/js/main.js +495 -0
  17. data/htdocs/{js → common/js}/vendor/angular-bootstrap-prettify.min.js +0 -0
  18. data/htdocs/{js → common/js}/vendor/angular-bootstrap.min.js +0 -0
  19. data/htdocs/{js → common/js}/vendor/angular-cookies.min.js +0 -0
  20. data/htdocs/{js → common/js}/vendor/angular-loader.min.js +0 -0
  21. data/htdocs/{js → common/js}/vendor/angular-resource.min.js +0 -0
  22. data/htdocs/{js → common/js}/vendor/angular-sanitize.min.js +0 -0
  23. data/htdocs/{js → common/js}/vendor/angular-ui-ieshiv.min.js +0 -0
  24. data/htdocs/{js → common/js}/vendor/angular-ui.min.js +0 -0
  25. data/htdocs/{js → common/js}/vendor/angular.js +0 -0
  26. data/htdocs/{js → common/js}/vendor/angular.min.js +0 -0
  27. data/htdocs/{js → common/js}/vendor/bootstrap.js +0 -0
  28. data/htdocs/{js → common/js}/vendor/bootstrap.min.js +0 -0
  29. data/htdocs/{js → common/js}/vendor/html5shiv.js +0 -0
  30. data/htdocs/{js → common/js}/vendor/jquery-1.8.2.min.js +0 -0
  31. data/htdocs/{templates → common/templates}/directory.html +2 -2
  32. data/htdocs/common/templates/error.html +6 -0
  33. data/htdocs/{templates → common/templates}/file.html +0 -0
  34. data/htdocs/{templates → common/templates}/git.html +0 -0
  35. data/htdocs/{templates → common/templates}/index.html +1 -1
  36. data/htdocs/{templates → common/templates}/index_entry.html +0 -0
  37. data/htdocs/{templates → common/templates}/info_refs.html +2 -2
  38. data/htdocs/{templates → common/templates}/loading.html +0 -0
  39. data/htdocs/{templates → common/templates}/notfound.html +1 -2
  40. data/htdocs/{templates → common/templates}/object.html +1 -1
  41. data/htdocs/{templates → common/templates}/objects.html +3 -3
  42. data/htdocs/{templates → common/templates}/pack_file.html +1 -1
  43. data/htdocs/common/templates/pack_index.html +39 -0
  44. data/htdocs/{templates → common/templates}/packed_object.html +4 -4
  45. data/htdocs/{templates → common/templates}/packed_refs.html +2 -2
  46. data/htdocs/{templates → common/templates}/ref.html +0 -0
  47. data/htdocs/common/templates/reflog.html +29 -0
  48. data/htdocs/config.js +6 -0
  49. data/htdocs/default.js +7 -0
  50. data/htdocs/index.html +52 -20
  51. data/lib/git-object-browser.rb +12 -4
  52. data/lib/git-object-browser/dumper/directories_dumper.rb +42 -0
  53. data/lib/git-object-browser/dumper/index_dumper.rb +20 -7
  54. data/lib/git-object-browser/dumper/info_refs_dumper.rb +37 -0
  55. data/lib/git-object-browser/dumper/main.rb +188 -81
  56. data/lib/git-object-browser/dumper/objects_dumper.rb +46 -0
  57. data/lib/git-object-browser/dumper/pack_indexes_dumper.rb +85 -0
  58. data/lib/git-object-browser/dumper/packed_objects_dumper.rb +36 -0
  59. data/lib/git-object-browser/dumper/packed_refs_dumper.rb +37 -0
  60. data/lib/git-object-browser/dumper/plain_files_dumper.rb +74 -0
  61. data/lib/git-object-browser/dumper/refs_dumper.rb +46 -0
  62. data/lib/git-object-browser/main.rb +22 -6
  63. data/lib/git-object-browser/models/directory.rb +5 -3
  64. data/lib/git-object-browser/models/git_date.rb +26 -0
  65. data/lib/git-object-browser/models/git_object.rb +1 -1
  66. data/lib/git-object-browser/models/pack_file.rb +1 -1
  67. data/lib/git-object-browser/models/pack_index.rb +139 -25
  68. data/lib/git-object-browser/models/packed_object.rb +1 -1
  69. data/lib/git-object-browser/models/reflog.rb +54 -0
  70. data/lib/git-object-browser/models/wrapped_object.rb +40 -0
  71. data/lib/git-object-browser/server/git_servlet.rb +130 -100
  72. data/lib/git-object-browser/server/main.rb +1 -1
  73. data/lib/git-object-browser/version.rb +1 -1
  74. metadata +62 -50
  75. data/htdocs/js/main.js +0 -285
  76. data/htdocs/templates/pack_index.html +0 -37
  77. data/lib/git-object-browser/dumper/object_dumper.rb +0 -20
  78. data/lib/git-object-browser/dumper/pack_index_dumper.rb +0 -21
  79. data/lib/git-object-browser/dumper/packed_object_dumper.rb +0 -19
data/README.md CHANGED
@@ -9,6 +9,23 @@ Browse git raw objects.
9
9
 
10
10
  ## Usage
11
11
 
12
+ To browse .git directory:
13
+
14
+ $ git object-browser ./path/to/project
15
+ $ open http://localhost:8080/#/.git
16
+
17
+ To dump .git directory (dump HTML/JSON/JS app):
18
+
19
+ $ git object-browser --dump path/to/dump/dir path/to/project
20
+ $ ${any_http_server} --port 8080 path/to/dump/dir
21
+ $ open http://localhost:8080/#/step1/.git/
22
+
23
+ To dump .git step by step:
24
+
25
+ $ git object-browser --dump path/to/dump/dir --next path/to/project
26
+
27
+ this command shows .git diff between previous step and current step.
28
+
12
29
  ## Contributing
13
30
 
14
31
  1. Fork it
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,495 @@
1
+ function routingConfig(steps) {
2
+ return function($routeProvider) {
3
+ $routeProvider = angular.extend($routeProvider, {
4
+
5
+ // AngularJS doesn't support regular expressions in routes.
6
+ // http://stackoverflow.com/questions/12685085/angularjs-route-how-to-match-star-as-a-path
7
+ 'whenPath': function(path, depth, route) {
8
+ for (var i = 1; i <= depth; i++) {
9
+ path += '/:path' + i;
10
+ this.when(path, route);
11
+ }
12
+ return this;
13
+ }
14
+ });
15
+ if (steps.length > 0) {
16
+ $routeProvider.
17
+ whenPath('/:basedir/.git', 10, {controller:GitCtrl, templateUrl:'common/templates/git.html'}).
18
+ otherwise({redirectTo:'/' + steps[0].name + '/.git/'});
19
+ } else {
20
+ $routeProvider.
21
+ whenPath('/.git', 10, {controller:GitCtrl, templateUrl:'common/templates/git.html'}).
22
+ otherwise({redirectTo:'/.git/'});
23
+ }
24
+ }
25
+ }
26
+
27
+ angular.module('GitObjectBrowser', ['ngResource'])
28
+ .config(routingConfig(config.steps))
29
+
30
+ .directive('scrollBottom', function() {
31
+ return function(scope, elm, attr) {
32
+ var rawDomElement = elm[0];
33
+ angular.element(window).unbind('scroll');
34
+ angular.element(window).bind('scroll', function() {
35
+ if (! scope.scrollBottomEnabled) return;
36
+
37
+ var rectObject = rawDomElement.getBoundingClientRect();
38
+ if (rectObject.bottom - window.innerHeight < 50) {
39
+ scope.$apply(attr.scrollBottom);
40
+ }
41
+ });
42
+ };
43
+ })
44
+
45
+ .directive('entryIcon', function($parse) {
46
+ return function(scope, element, attrs) {
47
+ var icons = {
48
+ 'directory': 'icon-folder-open',
49
+ 'ref': 'icon-map-marker',
50
+ 'reflog': 'icon-file',
51
+ 'info_refs': 'icon-map-marker',
52
+ 'packed_refs': 'icon-map-marker',
53
+ 'index': 'icon-list',
54
+ 'file': 'icon-file',
55
+ 'object': 'icon-comment',
56
+ 'blob': 'icon-file',
57
+ 'tree': 'icon-folder-open',
58
+ 'commit': 'icon-ok',
59
+ 'tag': 'icon-tag',
60
+ 'ofs_delta': 'icon-arrow-up',
61
+ 'ref_delta': 'icon-arrow-down'
62
+ };
63
+
64
+ var entryType = ($parse(attrs.entryIcon))(scope);
65
+ element.addClass(icons[entryType]);
66
+ }
67
+ })
68
+
69
+ .directive('modeIcon', function($parse) {
70
+ return function(scope, element, attrs) {
71
+ var mode = ($parse(attrs.modeIcon))(scope);
72
+ var iconClass;
73
+ if (120000 <= mode) {
74
+ iconClass = 'icon-share-alt';
75
+ } else if (100000 <= mode) {
76
+ iconClass = 'icon-file';
77
+ } else {
78
+ iconClass = 'icon-folder-open';
79
+ }
80
+ element.addClass(iconClass);
81
+ }
82
+ })
83
+
84
+ .directive('refHref', function($parse, $rootScope) {
85
+ return function(scope, element, attrs) {
86
+ var entry = ($parse(attrs.refHref))(scope);
87
+ var href = "";
88
+ var sha1 = null;
89
+
90
+ if (typeof(entry) == 'string') {
91
+ sha1 = entry;
92
+ } else if (entry && entry.sha1) {
93
+ sha1 = entry.sha1;
94
+ }
95
+
96
+ if (sha1 !== null) {
97
+ href = '#' + $rootScope.basedir + '/.git/objects/' + sha1.substr(0, 2) + '/' + sha1.substr(2);
98
+ } else if (entry && entry.ref) {
99
+ href = '#' + $rootScope.basedir + '/.git/' + entry.ref;
100
+ }
101
+
102
+ element.attr('href', href);
103
+ }
104
+ })
105
+
106
+ .filter('unixtime', function($filter) {
107
+ return function(input, format) {
108
+ return ($filter('date'))(input * 1000, format);
109
+ }
110
+ });
111
+
112
+ function GitCtrl($scope, $location, $routeParams, $rootScope, $resource, $http) {
113
+ if (! $rootScope.diffCache) $rootScope.diffCache = {};
114
+ if (! $rootScope.noteCache) $rootScope.noteCache = {};
115
+
116
+ // reset scrollBottom event handler
117
+ angular.element(window).unbind('scroll');
118
+
119
+ var objectTable = function(entries) {
120
+ var rows = [];
121
+ var hash = {};
122
+
123
+ angular.forEach(entries, function(entry) {
124
+ hash[entry.basename] = entry;
125
+ })
126
+
127
+ var hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
128
+ for (var i = 0; i < 16; i++) {
129
+ var cols = [];
130
+ for (var j = 0; j < 16; j++) {
131
+ if (hash[hex[i] + hex[j]]) {
132
+ cols[j] = hash[hex[i] + hex[j]];
133
+ } else {
134
+ cols[j] = {'basename': hex[i] + hex[j], 'type': 'empty'};
135
+ }
136
+ }
137
+ rows[i] = cols;
138
+ }
139
+ return rows;
140
+ }
141
+
142
+ var findIndexEntry = function(sha1) {
143
+ var entries = $scope.object.entries;
144
+ var entry = null;
145
+ angular.forEach(entries, function(value) {
146
+ if (value.sha1 == sha1) {
147
+ entry = value;
148
+ return;
149
+ }
150
+ });
151
+ return entry;
152
+ };
153
+
154
+ var indexEntryKeys = function(version) {
155
+ var keys = [
156
+ 'ctime',
157
+ 'cnano',
158
+ 'mtime',
159
+ 'mnano',
160
+ 'dev',
161
+ 'ino',
162
+ 'object_type',
163
+ 'unix_permission',
164
+ 'uid',
165
+ 'gid',
166
+ 'size',
167
+ 'sha1',
168
+ 'assume_valid_flag',
169
+ 'extended_flag',
170
+ 'stage',
171
+ 'name_length'
172
+ ]
173
+ if (version > 2) {
174
+ keys = keys.concat([
175
+ 'skip_worktree',
176
+ 'intent_to_add',
177
+ ]);
178
+ }
179
+ keys.push('path')
180
+
181
+ return keys;
182
+ };
183
+
184
+ var resourceLoaded = function(json) {
185
+ $scope.workingdir = json.workingdir;
186
+ $scope.root = json.root;
187
+ $scope.gitPath = json.path;
188
+ if (json.path == "") {
189
+ $scope.path = ".git";
190
+ } else {
191
+ $scope.path = ".git/" + json.path;
192
+ }
193
+ $scope.object = json.object;
194
+ $scope.keys = indexEntryKeys($scope.object.version);
195
+ var template;
196
+ if (json.path == "objects") {
197
+ template = "objects";
198
+ $scope.objectTable = objectTable($scope.object.entries);
199
+ loadDiffData();
200
+ } else if (json.type == "index" && $routeParams.sha1) {
201
+ template = "index_entry";
202
+ $scope.entry = findIndexEntry($routeParams.sha1);
203
+ } else if (json.type == "packed_refs" && $routeParams.ref) {
204
+ template = json.type;
205
+ var entries = [];
206
+ angular.forEach($scope.object.entries, function(entry) {
207
+ if (entry.ref == $routeParams.ref) {
208
+ entries.push(entry);
209
+ $scope.limited = true;
210
+ }
211
+ });
212
+ $scope.object.entries = entries;
213
+ } else if (json.type == "packed_object") {
214
+ template = json.type;
215
+ $scope.unpacked = json.unpacked;
216
+ } else if (json.type == "directory") {
217
+ template = json.type;
218
+ loadDiffData();
219
+ } else {
220
+ template = json.type;
221
+ }
222
+
223
+ $scope.template = 'common/templates/' + template + '.html';
224
+ };
225
+
226
+ var loadNote = function() {
227
+ if (! config.loadNote) return;
228
+ var basedir, url;
229
+ if ($rootScope.basedir) {
230
+ basedir = $rootScope.basedir;
231
+ url = 'notes' + basedir + '.html';
232
+ } else {
233
+ basedir = '';
234
+ url = 'note.html';
235
+ }
236
+ if ($rootScope.noteCache[basedir] !== undefined) {
237
+ $rootScope.note = $rootScope.noteCache[basedir];
238
+ return;
239
+ }
240
+ $http.get(url)
241
+ .success(function(data) {
242
+ $rootScope.noteCache[basedir] = data;
243
+ $rootScope.note = data;
244
+ }).error(function() {
245
+ $rootScope.noteCache[basedir] = '';
246
+ $rootScope.note = null;
247
+ });
248
+ };
249
+
250
+ var loadDiffData = function() {
251
+ if (! config.loadDiff) return;
252
+ var stepPath = $rootScope.basedir;
253
+ if (! stepPath) return;
254
+
255
+ $scope.diff = {}
256
+ var base = '.git/';
257
+ if ($scope.object.path !== '') {
258
+ base = base + $scope.object.path + '/';
259
+ }
260
+ angular.forEach($scope.object.entries, function(entry) {
261
+ $scope.diff[base + entry.basename] = null;
262
+ });
263
+
264
+ var cache = $rootScope.diffCache[stepPath];
265
+ if (cache) {
266
+ diffDataLoaded(cache);
267
+ return
268
+ }
269
+ $http.get('json' + stepPath + '/_diff.json').success(function(diffData) {
270
+ $rootScope.diffCache[stepPath] = diffData;
271
+ diffDataLoaded(diffData);
272
+ }).error(function() {
273
+ $rootScope.diffCache[stepPath] = [];
274
+ });
275
+ };
276
+
277
+ var diffDataLoaded = function(data) {
278
+ var newDiffData = {}
279
+ angular.forEach($scope.diff, function(value, key) {
280
+ newDiffData[key] = isDiffEntry(data, key);
281
+ });
282
+ $scope.diff = newDiffData;
283
+ }
284
+
285
+ var isDiffEntry = function(data, key) {
286
+ for(var i = 0; i < data.length; i++) {
287
+ if (('.git/' + data[i]).indexOf(key) === 0) {
288
+ return '#fee';
289
+ }
290
+ }
291
+ return null;
292
+ }
293
+
294
+ $scope.resourceError = function(path) {
295
+ return function(data, status, headers, config) {
296
+ if (status == 404) {
297
+ resourceNotFound(path);
298
+ } else {
299
+ $scope.status = status;
300
+ $scope.path = path;
301
+ $scope.template = 'common/templates/error.html';
302
+ }
303
+ };
304
+ };
305
+
306
+ var packedObjectFinder = function(sha1) {
307
+ var indexes = [];
308
+
309
+ var find = function() {
310
+ $http.get('json' + $rootScope.basedir + '/objects/pack.json')
311
+ .success(startLoadPackDigest)
312
+ .error(showNotFound);
313
+ };
314
+
315
+ var startLoadPackDigest = function(json) {
316
+ angular.forEach(json.object.entries, function(entry) {
317
+ if (entry.basename.match(/\.idx$/)) {
318
+ indexes.push(entry);
319
+ }
320
+ });
321
+ loadPackDigest();
322
+ };
323
+
324
+ var loadPackDigest = function() {
325
+ if (indexes.length == 0) {
326
+ showNotFound();
327
+ return;
328
+ }
329
+ var entry = indexes.shift();
330
+ $http.get('json' + $rootScope.basedir + '/objects/pack/' + entry.basename + '.json')
331
+ .success(findPackObject)
332
+ .error(showNotFound);
333
+ };
334
+
335
+ var findPackObject = function(json) {
336
+ var i = 0;
337
+ angular.forEach(json.object.entries, function(digestSha1) {
338
+ if (sha1 <= digestSha1) {
339
+ return;
340
+ }
341
+ i++;
342
+ });
343
+
344
+ if (i == 0) {
345
+ loadPackDigest();
346
+ return;
347
+ }
348
+
349
+ $http.get('json' + $rootScope.basedir + '/' + json.path + '/sha1/' + i + '.json')
350
+ .success(loadPagedIndex)
351
+ .error(showNotFound);
352
+ };
353
+
354
+ var loadPagedIndex = function(json) {
355
+ var found = false;
356
+ angular.forEach(json.object.entries, function(entry) {
357
+ if (entry.sha1 == sha1) {
358
+ var path = json.path.replace(/.idx$/, '.pack');
359
+ found = true;
360
+ $routeParams.offset = entry.offset;
361
+ loadJson([$rootScope.basedir, path]);
362
+ }
363
+ });
364
+ if (! found) loadPackDigest();
365
+ }
366
+
367
+ find();
368
+ };
369
+
370
+ var resourceNotFound = function(path) {
371
+ $scope.path = path;
372
+ if (path.match(/^json\/[^\/]+\/objects\/([0-9a-f]{2})\/([0-9a-f]{38})\.json$/)) {
373
+ packedObjectFinder(RegExp.$1 + RegExp.$2);
374
+ } else if (path.match(/^json\/[^\/]+\/(refs\/.+)\.json$/)) {
375
+ $routeParams.ref = RegExp.$1;
376
+ loadJson([$rootScope.basedir, 'packed-refs'])
377
+ } else {
378
+ $scope.template = 'common/templates/notfound.html';
379
+ }
380
+ };
381
+
382
+ var showNotFound = function() {
383
+ $scope.template = 'common/templates/notfound.html';
384
+ }
385
+
386
+ // ['', '/.git/xxx'] or
387
+ // ['/basedir', '/.git/xxx']
388
+ var buildPath = function() {
389
+ var path = '';
390
+ var basedir = '';
391
+ if ($routeParams['basedir'] !== undefined) {
392
+ basedir = '/' + $routeParams['basedir'];
393
+ }
394
+ for (var i = 1; i <= 10; i++) {
395
+ if ($routeParams['path' + i]) {
396
+ if (i > 1) path += '/';
397
+ path += $routeParams['path' + i];
398
+ }
399
+ }
400
+ return [basedir, path];
401
+ }
402
+
403
+ var loadJson = function(path) {
404
+ $rootScope.basedir = path[0];
405
+ $scope.template = 'common/templates/loading.html';
406
+
407
+ if (path[1].match(/^objects\/pack\/pack-[0-9a-f]{40}\.pack$/) && $routeParams.offset) {
408
+ var offset = '0000' + $routeParams.offset;
409
+ path = 'json' + path[0] + '/' + path[1]
410
+ + '/' + offset.slice(-2)
411
+ + '/' + offset.slice(-4, -2)
412
+ + '/' + $routeParams.offset + '.json';
413
+ } else if (path[1].match(/^objects\/pack\/pack-[0-9a-f]{40}\.idx$/)) {
414
+ var order = $routeParams.order == 'offset' ? 'offset' : 'sha1';
415
+ var page = $routeParams.page || 1;
416
+ path = 'json' + path[0] + '/' + path[1] + '/' + order + '/' + page + '.json';
417
+ } else {
418
+ if (path[1] == '') path[1] = '_git';
419
+ path = 'json' + path[0] + '/' + path[1] + '.json';
420
+ }
421
+ $http.get(path).success(resourceLoaded).error($scope.resourceError(path));
422
+ };
423
+
424
+ loadJson(buildPath());
425
+ loadNote();
426
+ }
427
+
428
+ function PackFileCtrl($scope, $location, $routeParams) {
429
+ $scope.indexUrl = $scope.path.replace(/.pack$/, '.idx');
430
+ }
431
+
432
+ function PackIndexCtrl($scope, $location, $routeParams, $rootScope, $resource, $http) {
433
+
434
+ $scope.packUrl = $scope.path.replace(/.idx$/, '.pack');
435
+ $scope.lastPage = 1;
436
+ $scope.scrollBottomEnabled = true;
437
+
438
+ var resourceLoaded = function(json) {
439
+ $scope.object.entries = $scope.object.entries.concat(json.object.entries);
440
+ var last_page = Math.ceil(json.entry_count / json.per_page);
441
+ $scope.scrollBottomEnabled = (json.page < last_page);
442
+ $scope.loading = false;
443
+ }
444
+
445
+ $scope.loadNextPage = function() {
446
+ $scope.lastPage += 1;
447
+
448
+ var order = $routeParams.order == 'offset' ? 'offset' : 'sha1';
449
+ var path = 'json' + $rootScope.basedir + '/' + $scope.gitPath + '/' + order + '/' + $scope.lastPage + '.json';
450
+
451
+ $http.get(path).success(resourceLoaded).error($scope.resourceError(path));
452
+ };
453
+
454
+ $scope.scrollBottom = function() {
455
+ $scope.scrollBottomEnabled = false;
456
+ $scope.loading = true;
457
+ $scope.loadNextPage();
458
+ }
459
+
460
+ }
461
+
462
+ function MenuCtrl($scope, $location, $routeParams) {
463
+ $scope.steps = config.steps;
464
+
465
+ $scope.stepPrev = function() {
466
+ var idx = getStepIndex();
467
+ if (idx.index > 0) {
468
+ $location.path('/' + $scope.steps[idx.index - 1].name + '/' + idx.file);
469
+ }
470
+ }
471
+
472
+ $scope.stepNext = function() {
473
+ var idx = getStepIndex();
474
+ if (idx.index < $scope.steps.length - 1) {
475
+ $location.path('/' + $scope.steps[idx.index + 1].name + '/' + idx.file);
476
+ }
477
+ }
478
+
479
+ var getStepIndex = function() {
480
+ var path = $location.path();
481
+ if (! path.match(/\/([^\/]+)\/(.+)/)) return null;
482
+
483
+ var stepName = RegExp.$1;
484
+ var file = RegExp.$2;
485
+ var obj = { stepName: stepName, file: file, index: 0 };
486
+
487
+ for (var i = 0; i < $scope.steps.length; i++) {
488
+ if (stepName == $scope.steps[i].name) {
489
+ obj.index = i;
490
+ return obj;
491
+ }
492
+ }
493
+ return obj;
494
+ }
495
+ }