@@ -63,3 +63,111 @@ Reference.prototype.isValid = function() {
6363Reference . prototype . toString = function ( ) {
6464 return this . name ( ) ;
6565} ;
66+
67+ const MAX_NESTING_LEVEL = 10 ;
68+
69+ const getTerminal = ( repo , refName , nesting , prevRef = null ) => {
70+ if ( nesting > MAX_NESTING_LEVEL ) {
71+ return Promise . resolve ( {
72+ error : NodeGit . Error . CODE . ENOTFOUND ,
73+ out : prevRef
74+ } ) ;
75+ }
76+
77+ return NodeGit . Reference . lookup ( repo , refName )
78+ . then ( ( ref ) => {
79+ if ( ref . type ( ) === NodeGit . Reference . TYPE . OID ) {
80+ return {
81+ error : NodeGit . Error . CODE . OK ,
82+ out : ref
83+ } ;
84+ } else {
85+ return getTerminal ( repo , ref . symbolicTarget ( ) , nesting + 1 , ref )
86+ . then ( ( { error, out } ) => {
87+ if ( error === NodeGit . Error . CODE . ENOTFOUND && ! out ) {
88+ return { error, out : ref } ;
89+ } else {
90+ return { error, out } ;
91+ }
92+ } ) ;
93+ }
94+ } )
95+ . catch ( ( error ) => {
96+ return {
97+ error : error . errno ,
98+ out : null
99+ } ;
100+ } ) ;
101+ } ;
102+
103+ const getSignatureForReflog = ( repo ) => {
104+ const { email, name } = repo . ident ( ) ;
105+ if ( email && name ) {
106+ return Promise . resolve ( NodeGit . Signature . now ( name , email ) ) ;
107+ }
108+
109+ return NodeGit . Signature . default ( repo )
110+ . catch ( ( ) => NodeGit . Signature . now ( "unknown" , "unknown" ) ) ;
111+ } ;
112+
113+ Reference . updateTerminal = function (
114+ repo ,
115+ refName ,
116+ oid ,
117+ signature ,
118+ logMessage
119+ ) {
120+ let signatureToUse ;
121+ let promiseChain = Promise . resolve ( ) ;
122+
123+ if ( ! signature ) {
124+ promiseChain = promiseChain
125+ . then ( ( ) => getSignatureForReflog ( repo ) )
126+ . then ( ( sig ) => {
127+ signatureToUse = sig ;
128+ return Promise . resolve ( ) ;
129+ } ) ;
130+ } else {
131+ signatureToUse = signature ;
132+ }
133+
134+ return promiseChain
135+ . then ( ( ) => getTerminal ( repo , refName , 0 ) )
136+ . then ( ( { error, out } ) => {
137+ if ( error === NodeGit . Error . CODE . ENOTFOUND && out ) {
138+ return NodeGit . Reference . create (
139+ repo ,
140+ out . symbolicTarget ( ) ,
141+ oid ,
142+ 0 ,
143+ logMessage
144+ ) ;
145+ } else if ( error === NodeGit . Error . CODE . ENOTFOUND ) {
146+ return NodeGit . Reference . create (
147+ repo ,
148+ refName ,
149+ oid ,
150+ 0 ,
151+ logMessage
152+ ) ;
153+ } else {
154+ return NodeGit . Reference . createMatching (
155+ repo ,
156+ out . name ( ) ,
157+ oid ,
158+ 1 ,
159+ out . target ( ) ,
160+ logMessage
161+ ) ;
162+ }
163+ } )
164+ . then ( ( ) => NodeGit . Reflog . read ( repo , refName ) )
165+ . then ( ( reflog ) => {
166+ // We may want some kind of transactional logic for this
167+ // There is a theoretical timing issue that could result in updating
168+ // the wrong reflog
169+ reflog . drop ( 0 , 1 ) ;
170+ reflog . append ( oid , signatureToUse , logMessage ) ;
171+ return reflog . write ( ) ;
172+ } ) ;
173+ } ;
0 commit comments