Subversion Command Line Primer

Linux No Comments

Below is an aggregate of my notes on how to use command line Subversion. The syntax may not be 100% correct (may have changed in newer versions) so please adapt accordingly.

Note: For more details, refer to the free book, Version Control with Subversion, written by some of the Subversion developers.

Though I’m using Linux syntax below, the Subversion commands should also work on Windows and macOS.

# Show version installed
svn --version

# ------------ Local Admin ------------

# Create a repository
sudo mkdir /var/repos
sudo svnadmin create /var/repos

# Export a repository
svnadmin dump /var/repos > backup.svn

# Import a repository
svnadmin load /var/repos < backup.svn

# List all projects in the local repository.
svn list file:///var/repos

# ------------ Basic Remote Client ------------

# List all projects in the remote repository by svn+ssh or HTTP URI.
svn list svn+ssh://myuser@mydomain.com/var/repos
svn --username <myuser> --password <mypassword> list http://mydomain.com/var/repos

# Import a project into the repository
svn import ./myproject svn+ssh://myuser@mydomain.com/var/repos/myproject -m "Initial Import"

# Check out a local, working copy of a project from the repository
svn co svn+ssh://myuser@mydomain.com/var/repos/myproject ./myproject

# View the working copy's info (no need to input the URI once inside the project)
cd ./myproject
svn info

# Update the project to the latest version
svn update

# Add a new file
svn add newfile.cpp

# Remove a file
svn rm oldfile.cpp

# Move and/or rename a file
svn mv oldfile.cpp subdir/newoldfile.cpp

# Set file to be binary type
svn propset svn:mime-type 'application/octet-stream' myfile.bin

# Have Subversion ignore certain subdirectories or files
svn propedit svn:ignore .

# List the modified files/directories (aka status) made to working copy
svn status
svn st

# Show differences between local files and current revision (usually HEAD)
svn diff

# Commit (aka checkin) all local working changes to the repository
svn commit -m "first commit"
svn ci -m "first commit"

# Show checkin logs (revision number, user, time, checkin comment)
svn log

# List files modified by a particular revision
svn log -v -r <revision_number>

# Show line-by-line differences in a particular revision's changeset
svn diff -c <revision_number>

# ------------ Selective Commit ------------

# Create changelist for selective commit
svn changelist <changelist-name> file1 file2 file3

# Add or remove files from the selective changelist
svn changelist <changelist-name> --add file4
svn changelist <changelist-name> --remove file2

# Show differences in selective changelist
svn diff --changelist <changelist-name>

# Checkin only files listed in selective changelist
svn ci -m "comment" --changelist <changelist-name>

# ------------ Undelete a File ------------

# Find version when deletion took place
svn log verbose

# Undelete by copying back from revision (one prior to deletion revision) to current
svn copy --revision 835 http://mydomain.com/myproject/myfile.cpp .

# If get "Path not found", then add a revision suffix to the URI
svn copy ‐‐revision 835 http://mydomain.com/myproject/myfile.cpp@835 .

# ------------ Switch to Previous Revision ------------

# Revert to previous revision
svn up -r [revision_number]

# Show files that have changed
svn st --show-updates

# diff against latest revision (diff by itself won't show any differences)
svn diff -r HEAD
   
# ------------ Branching and Merging ------------

# Find revision when branched from trunk
svn log -v --stop-on-copy

# Revert back to an earlier revision
svn merge -r 10340:10335 <file or dir>

# Merge just one file
svn merge -r10343:10739 https://mydomain.com/myproject/myfile.cpp ./myfile.cpp

# Merge from trunk to branch
svn merge --dry-run -r10810:HEAD https://mydomain.com/myproject/trunk/ .
svn merge -r10810:HEAD --accept mine-conflict https://mydomain.com/myproject/trunk/ .

# Merge from branch to trunk (automatically accept theirs-full if conflict)
svn merge --reintegrate --accept theirs-full https://mydomain.com/myproject/branches/mybranch .

# Update working copy to use a different branch
svn switch http://mydomain/myproject/branches/mybranch .
No Comments

Install LEMP on Ubuntu WSL on Windows 10

Windows Development No Comments

To facilitate web development, I wanted the same environment on my Windows 10 desktop as exists on my Ubuntu VPS server. With WSL (Windows Subsystem for Linux), I can have the same LEMP (Linux, Nginx, MySQL, and PHP) setup on my Windows 10 desktop.

See my previous post, Install Subversion on Ubuntu WSL on Windows 10, to get an Ubuntu-flavored WSL working on your Windows 10 system.

Instructions to install LEMP on Ubuntu WSL are almost the same as what I used to install LEMP on my Ubuntu server (see Install Ubuntu, LEMP, and WordPress on an Unmanaged VPS).

Install PHP

The latest Ubuntu WSL version is 18.04.1 LTS, which supports the latest PHP 7.2 version.

# Install PHP 7.2 and support packages:
# - php7.2-cli - PHP command line
# - php-mysql - PHP library to call MySQL database
# - php-fpm - PHP FastCGI Process Manager for Nginx integration
sudo apt install php7.2 php7.2-cli php7.2-mysql php7.2-fpm

# List the installed packages and grep for php-specific packages:
dpkg --get-selections | grep -i php

# Get the version of PHP installed
php -version

Install MySQL

# Install MySQL server.
sudo apt install mysql-server

# Get version of MySQL server and CLI installed
mysqld --version
mysql --version

# Start MySQL server
sudo service mysql start
sudo service mysql status

# Log into MySQL server as root user with blank password.
sudo mysql -u root
mysql> show databases;
mysql> quit

Note: Instead of using the “quit” command to exit the MySQL client, you can also use the “exit” command. Semi-colon termination (for example, “quit;” or “exit;”) are optional for these close connection commands.

By default, the MySQL server is configured to only allow root MySQL login from the root Linux user. Thus, we had to use “sudo mysql -u root” above. If we wish to allow a non-root Linux user to login using the root MySQL user (eliminate need for “sudo”), we’ll need to change how the root MySQL user is athenticated (switch to “mysql_native_password” plugin instead of the “auth_socket” plugin).

# Log into MySQL server as root user with blank password.
sudo mysql -u root

# Allow connection from a non-root Linux user
mysql> use mysql;
mysql> update user set plugin='mysql_native_password' where User='root';
mysql> flush privileges;

# Exit MySQL client.
mysql> quit

# Log into MySQL server as root user without "sudo".
mysql -u root
mysql> show databases;
mysql> quit

If you wish to secure the MySQL server, you can use the convenient “mysql_secure_installation” utility. Run the utility to enable password validation, set a root user password, remove anonymous users, disable remote root login, and remove the test database. You can re-run the utility again to reset the root user password if you need to.

# Run utility to secure MySQL server
sudo mysql_secure_installation

# Log into MySQL server as root user with password prompt
mysql -u root -p
mysql> show databases;
mysql> quit

If you wish to go back to using a blank MySQL root password, run the following to disable password validation and set a blank root password:

mysql -u root -p
mysql> uninstall plugin validate_password;
mysql> set PASSWORD for root@localhost=PASSWORD('');
mysql> quit

Install Nginx

# Install Nginx
sudo apt install nginx

# Start Nginx server
sudo service nginx start

Browse to http://localhost/ and you should see the initial Nginx welcome page.

Start the PHP-FPM service so Nginx can execute PHP scripts.

# Locate unix socket file which PHP-FPM service will listen to.
grep "listen =" /etc/php/7.2/fpm/pool.d/www.conf
# output: listen = /run/php/php7.2-fpm.sock

# Start PHP-FPM service.
sudo service php7.2-fpm start

Edit the default Nginx server block file to use the PHP-FPM service:

sudo nano /etc/nginx/sites-available/default

In the “default” server block file, change the following:

server {
        # Add index.php to the list if you are using PHP
        #index index.html index.htm index.nginx-debian.html;

        # Add index.php to front of "index" to execute it first
        index index.php index.html index.htm index.nginx-debian.html;

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;

                # Make sure unix socket path matches PHP-FPM configured path above
                fastcgi_pass unix:/run/php/php7.2-fpm.sock;

                # Prevent ERR_INCOMPLETE_CHUNKED_ENCODING when browser hangs on response
                fastcgi_buffering off;
        }
}

Restart the Nginx service to have the changes take effect:

sudo service nginx restart

Test PHP and MySQL Integration

Create a PHP test script by running this edit command:

sudo nano /var/www/html/info.php

In the “info.php” file, input the following content:

<?php
phpinfo();
?>

Browse to http://localhost/info.php and you should see a page containing information about the PHP installation.

Create a PHP MySQL test script by running this edit command:

sudo nano /var/www/html/mysql.php

In the “mysql.php” file, input the following content:

<?php
// HTML response header
header('Content-type: text/plain');

// Database connection parameters
$DB_HOST = 'localhost';
$DB_PORT = 3306; // 3306 is default MySQL port
$DB_USER = 'root';
$DB_PASS = ''; // blank or password (if you set one)
$DB_NAME = 'mysql'; // database instance name

// Open connection (all args can be optional or NULL!)
$mysqli = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME, $DB_PORT);
if ($mysqli->connect_error) {
  echo 'Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error . PHP_EOL;
} else {
  // Query users
  if ($result = $mysqli->query('SELECT User FROM user')) {
    echo 'Database users are:' . PHP_EOL;
    for ($i = 0; $i < $result->num_rows; $i++) {
      $result->data_seek($i);
      $row = $result->fetch_assoc();
      echo $row['User'] . PHP_EOL;
    }
    $result->close();
  } else {
    echo 'Query failed' . PHP_EOL;
  }
}

// Close connection
$mysqli->close();
?>

Browse to http://localhost/mysql.php and you should see a page listing the MySQL database users.

If you have problems, you can debug by enabling PHP-FPM error logging. Edit the configuration for the PHP-FPM pool:

# Edit www.conf file and add an error_log directive.
sudo nano /etc/php/7.2/fpm/pool.d/www.conf
    # Add an error log file location in the "/tmp" directory
    ;php_admin_value[error_log] = /var/log/fpm-php.www.log
    php_admin_value[error_log] = /tmp/fpm-php.log

# Restart PHP-FPM service for change to take effect
sudo service php7.2-fpm restart

Note: There exists a “/etc/php/7.2/fpm/php.ini” configuration file but that is not used by the Nginx PHP-FPM connection. Also, putting the error log file in a directory other than the “/tmp” directory (like “/var/log”) may not work due to permission issues.

Info above derived from:

No Comments

Install Subversion on Ubuntu WSL on Windows 10

Windows Development No Comments

I needed Subversion client access on a fresh Windows 10 installation. Rather than installing one of the Subversion clients for Windows (for example, CollabNet Subversion or SlikSVN), I decided to take advantage of the new WSL (Windows Subsystem for Linux).

The best part of macOS is the Linux system which macOS runs on. And now, the latest Windows 10 has something equivalent. Below are the steps I took to install WSL (Ubuntu flavor) and Subversion.

Install WSL Ubuntu

  1. Enable the WSL feature.
    • Run “Turn Windows features on or off” and check the box for the “Windows Subsystem for Linux” feature.
    • Alternatively, launch the Windows PowerShell as an administrator and run this command:
      Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  2. Restart the computer to finish enabling the WSL feature.
  3. Launch the “Windows Store” and search for “Run Linux on Windows”.
    • Click on Ubuntu (or your favorite flavor of Linux).
    • Click on Get (or Install) to install Ubuntu.
  4. Run the installed “Ubuntu” app to configure the WSL.
    • After several minutes, it will prompt you to input a Unix username and password for your default sudo user. (This will be the default user that your bash shell runs under.)
  5. You can run “Ubuntu” or “bash” to launch the bash terminal shell.
    • “Ubuntu” will put you in the “/home/<username>” directory.
    • “bash” will keep the current directory.
  6. Some Linux commands to try out:
    # Show version of Linux
    lsb_release -a

    # Show HOME variable and current directory
    echo $HOME
    pwd

    # Two ways to list the contents of the "C:\Program Files" directory
    ls "/mnt/c/Program Files"
    ls /mnt/c/Program\ Files

    # Log into root user
    sudo su

While it is easy to access the Windows drive from Ubuntu by using “/mnt/c” for the C:\ drive, the Linux root “/” directory maps to the Windows directory at “C:\Users\<username>\AppData\Local
\Packages\CanonicalGroupLimited.UbuntuonWindows_<UID>\LocalState\rootfs”.

I recommend creating a NTFS symbolic link to make it easier to access the Linux home directory. Open a Command Prompt as administrator and run this command:

mklink /d c:\ubuntu "C:\Users\<username>\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_<UID>\LocalState\rootfs"

Note: Strangely, if I create a new file in the Ubuntu’s rootfs directory using Windows, the file is not visible under the Ubuntu shell. Editing an existing file from Windows works fine.

Install Subversion

Installing Subversion on WSL Ubuntu is identical to installing Subversion on my unmanaged Ubuntu virtual server (see Subversion Over SSH on an Unmanaged VPS).

Note: You may notice the switch from the “apt-get” command to the “apt” command when installing and updating Ubuntu packages. The “apt” command is a slightly smaller subset of the “apt-get” command, more user-friendly, and appears to be the recommended command to use going forward.

Below are the steps I took to update Ubuntu, install Subversion, and connect to the remote Subversion repository on my server.

  1. Update Ubuntu packages using the bash shell:
    # Refresh the APT repository index
    # If you don't update, the install command below will fail.
    sudo apt update

    # List packages that can be upgraded
    apt list --upgradable

    # Upgrade packages with auto-handling of dependencies
    # (same as "apt-get dist-upgrade")
    sudo apt full-upgrade

    # Remove dependencies which are no longer used (frees up space)
    sudo apt autoremove
  2. Install Subversion:
    # Install subversion
    sudo apt install subversion

    # Check that subversion is installed
    svn --version
  3. Because my server uses a custom SSH port and requires the Subversion client to use the SVN+SSH protocol, we must configure SSH to use the custom port automatically because there is no option to input the custom port on the command line.
    # Create .ssh configuration directory under the home directory
    mkdir ~/.ssh

    # Optionally, restrict access to the directory to just the user/owner
    chmod 700 ~/.ssh

    # Create SSH config file
    cat > ~/.ssh/config
    Host mydomain.com
      Port 3333
      PreferredAuthentications publickey,password
    # Press CTRL-D to save and exit the file

    # SSH requires that only the user has access to files under the ~/.ssh directory.
    # If you don't restrict, SSH will throw a "Bad owner or permissions" warning and ignore the files.
    chmod 600 ~/.ssh/config

    # Copy the trusted client "id_rsa" and "id_rsa.pub" identity files to the ~/.ssh directory
    # to eliminate the need to input the password when using SSH.
  4. Connect to the remote Subversion repository:
    # List all projects in the remote repository.
    svn list svn+ssh://mynewuser@mydomain.com/var/repos

    # Check out a local, working copy of the project from the repository
    svn co svn+ssh://mynewuser@mydomain.com/var/repos/myproject ./myproject

    # View the working copy's info (no need to input the svn+ssh URL once inside the project)
    cd ./myproject
    svn info

See my followup post, Install LEMP on Ubuntu WSL on Windows 10, for instructions on getting a full LEMP (Linux, Nginx, MySQL, PHP) development environment working on Ubuntu WSL.

Info above derived from:

No Comments