@@ -29,6 +29,13 @@ define(function (require) {
2929 commitCache = [ ] ,
3030 lastDocumentSeen = null ;
3131
32+ // must match the page size git log is invoked with in GitCli.getHistory
33+ const HISTORY_PAGE_SIZE = 100 ;
34+
35+ // guards against an older async render/load overwriting a newer one
36+ let historyRenderId = 0 ,
37+ loadingMoreHistory = false ;
38+
3239 // Implementation
3340
3441 function initVariables ( ) {
@@ -90,49 +97,78 @@ define(function (require) {
9097 return author + email ;
9198 } ) ;
9299
93- // Render history list the first time
100+ function _renderHistoryTable ( commits , file ) {
101+ // calculate some missing stuff like avatars
102+ commits = addAdditionalCommitInfo ( commits ) ;
103+ commitCache = commitCache . concat ( commits ) ;
104+
105+ const templateData = {
106+ commits : commits ,
107+ emptyMessage : file ? Strings . GIT_FILE_HISTORY_NOTHING_TO_SHOW : Strings . GIT_HISTORY_NOTHING_TO_SHOW ,
108+ Strings : Strings
109+ } ;
110+
111+ $tableContainer . find ( "#git-history-list" ) . remove ( ) ;
112+ $tableContainer . append ( Mustache . render ( gitPanelHistoryTemplate , templateData , {
113+ commits : gitPanelHistoryCommitsTemplate
114+ } ) ) ;
115+
116+ $historyList = $tableContainer . find ( "#git-history-list" )
117+ . data ( "file" , file ? file . absolute : null )
118+ . data ( "file-relative" , file ? file . relative : null ) ;
119+
120+ if ( commits . length < HISTORY_PAGE_SIZE ) {
121+ // the full history is already here, so the last commit is the initial
122+ // one. with more pages the initial commit is marked by loadMoreHistory.
123+ $historyList . attr ( "x-finished" , "true" ) ;
124+ $historyList
125+ . find ( "tr.history-commit:last-child" )
126+ . attr ( "x-initial-commit" , "true" ) ;
127+ }
128+ }
129+
130+ // Render history list the first time. resolves to false when rendering failed.
94131 function renderHistory ( file ) {
132+ const renderId = ++ historyRenderId ;
133+
95134 // clear cache
96135 commitCache = [ ] ;
97136
98137 return Git . getCurrentBranchName ( ) . then ( function ( branchName ) {
99138 // Get the history commits of the current branch
100139 var p = file ? Git . getFileHistory ( file . relative , branchName ) : Git . getHistory ( branchName ) ;
101140 return p . then ( function ( commits ) {
102-
103- // calculate some missing stuff like avatars
104- commits = addAdditionalCommitInfo ( commits ) ;
105- commitCache = commitCache . concat ( commits ) ;
106-
107- var templateData = {
108- commits : commits ,
109- Strings : Strings
110- } ;
111-
112- $tableContainer . append ( Mustache . render ( gitPanelHistoryTemplate , templateData , {
113- commits : gitPanelHistoryCommitsTemplate
114- } ) ) ;
115-
116- $historyList = $tableContainer . find ( "#git-history-list" )
117- . data ( "file" , file ? file . absolute : null )
118- . data ( "file-relative" , file ? file . relative : null ) ;
119-
120- $historyList
121- . find ( "tr.history-commit:last-child" )
122- . attr ( "x-initial-commit" , "true" ) ;
141+ if ( renderId === historyRenderId ) {
142+ _renderHistoryTable ( commits , file ) ;
143+ }
144+ return true ;
123145 } ) ;
124146 } ) . catch ( function ( err ) {
147+ if ( renderId !== historyRenderId ) {
148+ return true ;
149+ }
150+ // "bad revision"/"unknown revision" mean the branch has no commit
151+ // yet (freshly initialized repository), so there is just no history
152+ // to show and that is not an error
153+ if ( ErrorHandler . contains ( err , "bad revision" ) || ErrorHandler . contains ( err , "unknown revision" ) ) {
154+ _renderHistoryTable ( [ ] , file ) ;
155+ return true ;
156+ }
125157 ErrorHandler . showError ( err , Strings . ERROR_GET_HISTORY ) ;
158+ return false ;
126159 } ) ;
127160 }
128161
129162 // Load more rows in the history list on scroll
130163 function loadMoreHistory ( ) {
131164 if ( $historyList . is ( ":visible" ) ) {
132- if ( ( $tableContainer . prop ( "scrollHeight" ) - $tableContainer . scrollTop ( ) ) === $tableContainer . height ( ) ) {
133- if ( $historyList . attr ( "x-finished" ) === "true" ) {
165+ // 2px tolerance as scroll positions can be fractional on scaled displays
166+ if ( ( $tableContainer . prop ( "scrollHeight" ) - $tableContainer . scrollTop ( ) ) <= $tableContainer . height ( ) + 2 ) {
167+ if ( loadingMoreHistory || $historyList . attr ( "x-finished" ) === "true" ) {
134168 return ;
135169 }
170+ loadingMoreHistory = true ;
171+ const renderId = historyRenderId ;
136172 return Git . getCurrentBranchName ( ) . then ( function ( branchName ) {
137173 var p ,
138174 file = $historyList . data ( "file-relative" ) ,
@@ -143,6 +179,10 @@ define(function (require) {
143179 p = Git . getHistory ( branchName , skipCount ) ;
144180 }
145181 return p . then ( function ( commits ) {
182+ if ( renderId !== historyRenderId ) {
183+ // the list was re-rendered while this page was loading
184+ return ;
185+ }
146186 if ( commits . length === 0 ) {
147187 $historyList . attr ( "x-finished" , "true" ) ;
148188 // marks initial commit as first
@@ -168,6 +208,9 @@ define(function (require) {
168208 } )
169209 . catch ( function ( err ) {
170210 ErrorHandler . showError ( err , Strings . ERROR_GET_CURRENT_BRANCH ) ;
211+ } )
212+ . finally ( function ( ) {
213+ loadingMoreHistory = false ;
171214 } ) ;
172215 }
173216 }
@@ -286,8 +329,19 @@ define(function (require) {
286329 $historyList . remove ( ) ;
287330 }
288331 var $spinner = $ ( "<div class='spinner spin large'></div>" ) . appendTo ( $gitPanel ) ;
289- renderHistory ( file ) . finally ( function ( ) {
332+ renderHistory ( file ) . then ( function ( rendered ) {
290333 $spinner . remove ( ) ;
334+ if ( ! rendered ) {
335+ // rendering failed, go back to the changes view instead of
336+ // leaving an empty table container behind
337+ $tableContainer . find ( ".git-edited-list" ) . show ( ) ;
338+ $gitPanel . find ( ".git-history-toggle" ) . removeClass ( "active" )
339+ . attr ( "title" , Strings . TOOLTIP_SHOW_HISTORY ) ;
340+ $gitPanel . find ( ".git-file-history" ) . removeClass ( "active" )
341+ . attr ( "title" , Strings . TOOLTIP_SHOW_FILE_HISTORY ) ;
342+ Git . status ( ) ;
343+ return ;
344+ }
291345 if ( isRefresh ) {
292346 // After rendering, we need to fetch the newly created #git-history-list
293347 let $newHistoryList = $tableContainer . find ( "#git-history-list" ) ;
@@ -327,6 +381,8 @@ define(function (require) {
327381 initVariables ( ) ;
328382 } ) ;
329383 EventEmitter . on ( Events . GIT_DISABLED , function ( ) {
384+ // invalidate any render still in flight so it can't repopulate the panel
385+ historyRenderId ++ ;
330386 lastDocumentSeen = null ;
331387 $historyList . remove ( ) ;
332388 $historyList = $ ( ) ;
0 commit comments