@ -51,6 +51,8 @@
package org.eclipse.jgit.lib ;
package org.eclipse.jgit.lib ;
import java.io.File ;
import java.io.IOException ;
import java.text.MessageFormat ;
import java.text.MessageFormat ;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Collections ;
import java.util.Collections ;
@ -64,6 +66,8 @@ import org.eclipse.jgit.events.ConfigChangedListener;
import org.eclipse.jgit.events.ListenerHandle ;
import org.eclipse.jgit.events.ListenerHandle ;
import org.eclipse.jgit.events.ListenerList ;
import org.eclipse.jgit.events.ListenerList ;
import org.eclipse.jgit.internal.JGitText ;
import org.eclipse.jgit.internal.JGitText ;
import org.eclipse.jgit.util.IO ;
import org.eclipse.jgit.util.RawParseUtils ;
import org.eclipse.jgit.util.StringUtils ;
import org.eclipse.jgit.util.StringUtils ;
@ -75,6 +79,7 @@ public class Config {
private static final long KiB = 1024 ;
private static final long KiB = 1024 ;
private static final long MiB = 1024 * KiB ;
private static final long MiB = 1024 * KiB ;
private static final long GiB = 1024 * MiB ;
private static final long GiB = 1024 * MiB ;
private static final int MAX_DEPTH = 999 ;
/** the change listeners */
/** the change listeners */
private final ListenerList listeners = new ListenerList ( ) ;
private final ListenerList listeners = new ListenerList ( ) ;
@ -633,12 +638,13 @@ public class Config {
private String getRawString ( final String section , final String subsection ,
private String getRawString ( final String section , final String subsection ,
final String name ) {
final String name ) {
String [ ] lst = getRawStringList ( section , subsection , name ) ;
String [ ] lst = getRawStringList ( section , subsection , name ) ;
if ( lst ! = null )
if ( lst ! = null ) {
return lst [ 0 ] ;
return lst [ lst . length - 1 ] ;
else if ( baseConfig ! = null )
} else if ( baseConfig ! = null ) {
return baseConfig . getRawString ( section , subsection , name ) ;
return baseConfig . getRawString ( section , subsection , name ) ;
else
} else {
return null ;
return null ;
}
}
}
private String [ ] getRawStringList ( String section , String subsection ,
private String [ ] getRawStringList ( String section , String subsection ,
@ -1026,6 +1032,15 @@ public class Config {
* made to { @code this } .
* made to { @code this } .
* /
* /
public void fromText ( final String text ) throws ConfigInvalidException {
public void fromText ( final String text ) throws ConfigInvalidException {
state . set ( newState ( fromTextRecurse ( text , 1 ) ) ) ;
}
private List < ConfigLine > fromTextRecurse ( final String text , int depth )
throws ConfigInvalidException {
if ( depth > MAX_DEPTH ) {
throw new ConfigInvalidException (
JGitText . get ( ) . tooManyIncludeRecursions ) ;
}
final List < ConfigLine > newEntries = new ArrayList < ConfigLine > ( ) ;
final List < ConfigLine > newEntries = new ArrayList < ConfigLine > ( ) ;
final StringReader in = new StringReader ( text ) ;
final StringReader in = new StringReader ( text ) ;
ConfigLine last = null ;
ConfigLine last = null ;
@ -1084,11 +1099,38 @@ public class Config {
} else
} else
e . value = readValue ( in , false , - 1 ) ;
e . value = readValue ( in , false , - 1 ) ;
if ( e . section . equals ( "include" ) ) { //$NON-NLS-1$
addIncludedConfig ( newEntries , e , depth ) ;
}
} else
} else
throw new ConfigInvalidException ( JGitText . get ( ) . invalidLineInConfigFile ) ;
throw new ConfigInvalidException ( JGitText . get ( ) . invalidLineInConfigFile ) ;
}
}
state . set ( newState ( newEntries ) ) ;
return newEntries ;
}
private void addIncludedConfig ( final List < ConfigLine > newEntries ,
ConfigLine line , int depth ) throws ConfigInvalidException {
if ( ! line . name . equals ( "path" ) | | //$NON-NLS-1$
line . value = = null | | line . value . equals ( MAGIC_EMPTY_VALUE ) ) {
throw new ConfigInvalidException (
JGitText . get ( ) . invalidLineInConfigFile ) ;
}
File path = new File ( line . value ) ;
try {
byte [ ] bytes = IO . readFully ( path ) ;
String decoded ;
if ( isUtf8 ( bytes ) ) {
decoded = RawParseUtils . decode ( RawParseUtils . UTF8_CHARSET ,
bytes , 3 , bytes . length ) ;
} else {
decoded = RawParseUtils . decode ( bytes ) ;
}
newEntries . addAll ( fromTextRecurse ( decoded , depth + 1 ) ) ;
} catch ( IOException ioe ) {
throw new ConfigInvalidException ( MessageFormat . format (
JGitText . get ( ) . invalidIncludedPathInConfigFile , path ) ) ;
}
}
}
private ConfigSnapshot newState ( ) {
private ConfigSnapshot newState ( ) {
@ -1108,6 +1150,19 @@ public class Config {
state . set ( newState ( ) ) ;
state . set ( newState ( ) ) ;
}
}
/ * *
* Check if bytes should be treated as UTF - 8 or not .
*
* @param bytes
* the bytes to check encoding for .
* @return true if bytes should be treated as UTF - 8 , false otherwise .
* @since 4 . 4
* /
protected boolean isUtf8 ( final byte [ ] bytes ) {
return bytes . length > = 3 & & bytes [ 0 ] = = ( byte ) 0xEF
& & bytes [ 1 ] = = ( byte ) 0xBB & & bytes [ 2 ] = = ( byte ) 0xBF ;
}
private static String readSectionName ( final StringReader in )
private static String readSectionName ( final StringReader in )
throws ConfigInvalidException {
throws ConfigInvalidException {
final StringBuilder name = new StringBuilder ( ) ;
final StringBuilder name = new StringBuilder ( ) ;