@@ -180,8 +180,96 @@ impl pubgrub::version::Version for Version {
180180 }
181181
182182 fn bump ( & self ) -> Self {
183- self . bump_patch ( )
183+ if self . is_pre ( ) {
184+ let mut pre = self . pre . clone ( ) ;
185+ let last_component = pre
186+ . last_mut ( )
187+ // This `.expect` is safe, as we know there to be at least
188+ // one pre-release component.
189+ . expect ( "no pre-release components" ) ;
190+
191+ match last_component {
192+ Identifier :: Numeric ( pre) => * pre += 1 ,
193+ Identifier :: AlphaNumeric ( pre) => {
194+ let mut segments = split_alphanumeric ( & pre) ;
195+ let last_segment = segments. last_mut ( ) . unwrap ( ) ;
196+
197+ match last_segment {
198+ AlphaOrNumeric :: Numeric ( n) => * n += 1 ,
199+ AlphaOrNumeric :: Alpha ( alpha) => {
200+ // We should potentially be smarter about this (for instance, pick the next letter in the
201+ // alphabetic sequence), however, this seems like it could be quite a bit more complex.
202+ alpha. push_str ( "1" )
203+ }
204+ }
205+
206+ * pre = segments
207+ . into_iter ( )
208+ . map ( |segment| match segment {
209+ AlphaOrNumeric :: Alpha ( segment) => segment,
210+ AlphaOrNumeric :: Numeric ( segment) => segment. to_string ( ) ,
211+ } )
212+ . collect :: < Vec < _ > > ( )
213+ . join ( "" ) ;
214+ }
215+ }
216+
217+ Self {
218+ major : self . major ,
219+ minor : self . minor ,
220+ patch : self . patch ,
221+ pre,
222+ build : None ,
223+ }
224+ } else {
225+ self . bump_patch ( )
226+ }
227+ }
228+ }
229+
230+ enum AlphaOrNumeric {
231+ Alpha ( String ) ,
232+ Numeric ( u32 ) ,
233+ }
234+
235+ /// Splits the given string into alphabetic and numeric segments.
236+ fn split_alphanumeric ( str : & str ) -> Vec < AlphaOrNumeric > {
237+ let mut segments = Vec :: new ( ) ;
238+ let mut current_segment = String :: new ( ) ;
239+ let mut previous_char_was_numeric = None ;
240+
241+ for char in str. chars ( ) {
242+ let is_numeric = char. is_ascii_digit ( ) ;
243+ match previous_char_was_numeric {
244+ Some ( previous_char_was_numeric) if previous_char_was_numeric == is_numeric => {
245+ current_segment. push ( char)
246+ }
247+ _ => {
248+ if !current_segment. is_empty ( ) {
249+ if current_segment. chars ( ) . any ( |char| char. is_ascii_digit ( ) ) {
250+ segments. push ( AlphaOrNumeric :: Numeric ( current_segment. parse ( ) . unwrap ( ) ) ) ;
251+ } else {
252+ segments. push ( AlphaOrNumeric :: Alpha ( current_segment) ) ;
253+ }
254+
255+ current_segment = String :: new ( ) ;
256+ }
257+
258+ current_segment. push ( char) ;
259+ previous_char_was_numeric = Some ( is_numeric) ;
260+ }
261+ }
184262 }
263+
264+ if !current_segment. is_empty ( ) {
265+ if current_segment. chars ( ) . any ( |char| char. is_ascii_digit ( ) ) {
266+ segments. push ( AlphaOrNumeric :: Numeric ( current_segment. parse ( ) . unwrap ( ) ) ) ;
267+ } else {
268+ segments. push ( AlphaOrNumeric :: Alpha ( current_segment) ) ;
269+ }
270+ }
271+
272+ segments
185273}
186274
187275impl < ' a > TryFrom < & ' a str > for Version {
0 commit comments