A directory

No toss of the front end, and salted fish what’s the difference

directory
A directory
The preface
A three-node solution for writing bash scripts
Quad preprogramming
V. Closing the port
Delete files/folders
Seven Git operation
 7.1 Git Commands commonly used in work
 7.2 Switching Branches
Eight summary
Ix references

The preface

Returns the directory

Today jsliang had another good time at work, opening the VIP channel:

  1. Automatically downloads Excel files
  2. Copy to the specified directory
  3. Perform multi-language import operations
  4. Resources to importgit pushGo up

Although it looks like a rough operation like this, there is nothing to say.

However, in the process of operation, it may be more cumbersome, such as the git operation after only importing resources:

  1. Add staging area:git add .
  2. Switch branches:git checkout -b <branch>
  3. Commit to a local repository:Git commit -m "feat: "#master_0720"
  4. Commit remote branch:git push --set-upstream origin <branch>

Not only that, but you also need to check that your multilingual resources are added and that the build goes through before you commit…


So, all this talk is really just to lead to the operation of bash instructions.

At work, you might encounter:

  • Git Series operations
  • None Example Disable an occupied system port
  • Delete a specified file/folder

However, you may forget the instructions for these operations in a short time, or the instructions are too tedious, so Jsliang thought it would be easier to install them.

A three-node solution for writing bash scripts

Returns the directory

In fact, jsliang is not bothered with this solution, so it goes directly to ShellJS:

  • ShellJS – Unix shell commands for Node.js

If a small partner feels that this is a bit abrupt, hope to have a reference comparison, you can see:

  • Node.js is the ultimate way to write bash scripts

The author compared Node’s own child_process API, ShellJS and ZX, and finally adopted ZX’s scheme.

Of course, jsliang works with ShellJS, so you don’t want to explore the same library, so install ShellJS ~

  • Installation:npm i shelljs
  • Install TS compile:npm i @types/shelljs -D

Install finished, start to toss!

Quad preprogramming

Returns the directory

To make the code look less smelly and long.

After jsliang wrote the article, he read the whole article more than 3 times. This is where the repeated code and problems in the following sections come in, so please read this chapter carefully before you copy the code

warn! please read the following carefully

The full contents are as follows:

Then repeat the code as follows:

src/common/index.ts

import { inquirer } from '.. /base/inquirer';
import { Result } from '.. /base/interface';

// System operation
import { sortCatalog } from '.. /base/file/sortDir';
import { deleteDir } from '.. /base/file/deleteDir';

/ / language
import { downLoadExcel } from './language/download';
import { importLanguage } from './language/import';
import { exportLanguage } from './language/export';

/ / shell operations
import { closePort } from '.. /base/shell/closePort';
import { gitCheckout } from '.. /base/shell/gitCheckout';

// Problem recorder
const answers = {
  q0: ' '.q1: ' '.q2: ' '.q3: ' '.q4: ' '.q5: ' '.q6: ' '.q7: ' '.q8: ' '};const common = (): void= > {
  // For the question route, see questionlist.ts
  const questionList = [
    // q0
    {
      type: 'list'.message: 'May I help you? '.choices: ['Public Service'.'Multilingual'],},// q1
    {
      type: 'list'.message: 'Current public services are:'.choices: ['File sort'.'Close port'.'Delete folder'.'Git operation'],},// q2
    {
      type: 'input'.message: 'Which folder do you want to sort? (absolute path) ',},// q3
    {
      type: 'list'.message: 'What support does multilanguage need? '.choices: [
        'Download multilingual resources'.'Importing multilingual resources'.'Export multilingual resources',]},// q4
    {
      type: 'input'.message: 'Where to download resources (HTTP)? '.default: 'https://www.kdocs.cn/l/sdwvJUKBzkK2',},// q5
    {
      type: 'input'.message: 'Which port do you need to close? ',},// q6
    {
      type: 'input'.message: 'What path do you want to delete? (full path) ',},// q7
    {
      type: 'list'.message: 'What support does Git need? '.choices: [
        'Switch branches'.// More...],},// q8
    {
      type: 'inupt'.message: 'Git branch name? ',},];const answerList = [
    // q0 - How can I help you?
    async (result: Result, questions: any) => {
      answers.q0 = result.answer;
      switch (result.answer) {
        case 'Public Service':
          questions[1] ();break;
        case 'Multilingual':
          questions[3] ();break;
        default: break; }},// q1 - Current public services are:
    async (result: Result, questions: any) => {
      answers.q1 = result.answer;
      switch (result.answer) {
        case 'File sort': questions[2] ();break;
        case 'Close port': questions[5] ();break;
        case 'Delete folder': questions[6] ();break;
        case 'Git operation': questions[7] ();break;
        default: break; }},// q2 - what is the folder to be sorted? (Absolute path)
    async (result: Result, _questions: any, prompts: any) => {
      answers.q2 = result.answer;
      const sortResult = await sortCatalog(result.answer);
      if (sortResult) {
        console.log('Sort successfully! '); prompts.complete(); }},// q3 - What support is required for multiple languages?
    async (result: Result, questions: any, prompts: any) => {
      answers.q3 = result.answer;
      switch (result.answer) {
        case 'Download multilingual resources':
        case 'Importing multilingual resources':
          questions[4] ();break;
        case 'Export multilingual resources':
          const exportResult = await exportLanguage();
          if (exportResult) {
            console.log('Export successful! ');
            prompts.complete();
          }
        default: break; }},// q4 - Resource download address (HTTP)?
    async (result: Result) => {
      answers.q4 = result.answer;
      const download = async() :Promise<any> => {
        const downloadResult = await downLoadExcel(result.answer);
        if (downloadResult) {
          console.log('Download successful! ');
          return true; }};switch (answers.q3) {
        case 'Download multilingual resources':
          await download();
          break;
        case 'Importing multilingual resources':
          await download();
          const importResult = await importLanguage();
          if (importResult) {
            console.log('Import finished! ');
          }
        default:
          break; }},// q5 - which port do you want to close?
    async (result: Result, _questions: any, prompts: any) => {
      answers.q5 = result.answer;
      const closeResult = await closePort(result.answer);
      if (closeResult) {
        console.log('Closed successfully'); prompts.complete(); }},// q6 - what path do you want to delete? (Full path)
    async (result: Result, _questions: any, prompts: any) => {
      answers.q6 = result.answer;
      const deleteResult = await deleteDir(result.answer);
      if (deleteResult) {
        console.log('Deletion succeeded'); prompts.complete(); }},// q7 - What support does Git need?
    async (result: Result, questions: any) => {
      answers.q7 = result.answer;
      questions[8] (); },// q8 -git branch name?
    async (result: Result, _questions: any, prompts: any) => {
      answers.q8 = result.answer;
      const checkoutResult = await gitCheckout(result.answer);
      if (checkoutResult) {
        console.log('Switchover successful'); prompts.complete(); }},]; inquirer(questionList, answerList); };export default common;

Copy the code

src/common/questionList.ts

// The common section of the question consultation route
export const questionList = {
  'Public Service': { // q0
    'File sort': { // q1
      'Folders to sort': 'the Work Work'.// q2
    },
    'Close port': { // q1
      'Ports to close': 'the Work Work'.// q5
    },
    'Delete folder': { // q1
      'Path to delete': 'the Work Work'.// q6
    },
    'Git operation': { // q1
      'Switch branches': { // q7
        'Branch name': 'the Work Work'.// q8}},},'Multilingual': { // q0
    'Download multilingual resources': { // q3
      'Download address': 'the Work Work'.// q4
    },
    'Importing multilingual resources': { // q3
      'Download address': 'the Work Work'.// q4
    },
    'Export multilingual resources': { // q3
      'Export full resources': 'the Work Work'.'Export a single gate resource': 'the Work Work',}}};Copy the code

The following passage shows that:

Update the SRC/common/index. Ts

Update the SRC/common/questionList. Ts

In this case, friends do not need to operate, this article has 3 places have this description.

Also, to avoid reporting TypeScript errors when referencing and running code, the three new files are listed below:

src/base/file/deleteDir.ts

import shell from 'shelljs';

export const deleteDir = async (path: string): Promise<boolean> => {
  console.log(path)
};
Copy the code

src/base/shell/closePort.ts

import shell from 'shelljs';

export const closePort = async (port: string): Promise<boolean> => {
  console.log(port);
};
Copy the code

src/base/shell/gitCheckout.ts

import shell from 'shelljs';

/ * * *@name Switch branches@description * 1. Git checkout ${branch} * 2@param {string} Branch Branch name */
export const gitCheckout = (branch: string): boolean= > {
  console.log(branch)
};
Copy the code

In addition, sortcatalog. ts under common has been migrated to base/file and renamed sortdir.ts.

So, ready, start output!

V. Closing the port

Returns the directory

When starting some magical services, you will encounter a scenario where the port is occupied, and you need to close the port:

  • Check whether a port is occupied:Netstat ano | findstr searches "port"
PS: F \ XXX > netstat ano | findstr searches "3001" TCP 0.0.0.0:3001 0.0.0.0:0 33396 TCP 10.13.144.170 LISTENING: 63001 183.2.199.241:443 ESTABLISHED 28228 TCP [::]:3001 [::]:0 LISTENING 33396Copy the code
  • Termination of PID:Taskkill -f-pid Specifies the PID number
PS F:\ XXX > taskkill -f -pid 33396 Succeeded: the process with PID 33396 has been terminated.Copy the code

If you’re in the Node library, you don’t want to do this yourself.

Update the SRC/common/index. Ts

Update the SRC/common/questionList. Ts

Then write closePort.ts:

src/base/shell/closePort.ts

import shell from 'shelljs';

export const closePort = async (port: string): Promise<boolean> => {
  await shell.exec(`netstat -ano | findstr :${port}`);

  // In Windows, a list of occupied ports is returned, which needs to be deleted by yourself
  console.log('The above list has been found, please run the command to delete the port: taskkill -f -pid PID number'); 

  return await true;
};
Copy the code

Note: The PID number is at the end of the printed result in Windows

Of course, since 3001 May have several IP ports, we only did the following step instead of shutting down all ports of 3001 (which requires manual operation by the user).

But it’s better than trying to memorize it (Windows, Mac, etc.)

Run NPM run jsliang. The result is as follows:

In this way, we have sealed the close port, because it is not a key to completely close, the practical index to the ☆☆☆

Delete files/folders

Returns the directory

In order to study how Windows can quickly remove node_modules, Jsliang actually looked at the data and found 3 ways to delete files/folders:

  1. cmd.exe:rd /s /q <path>
  2. PowerShell:rd -r <path>
  3. Mac:rm -rf <path>

In my own experience, on the company’s 32GB, 500 SSD desktop computer, PowerShell is faster to delete than cmd.exe (don’t ask me why, it’s faster, just personal experience, not science).

Then look at ShellJS, there is a way to delete:

  • ShellJS:rm()Delete files,rm('rf', <path>)Deleting a folder

Of course! In the spirit of exploration, let’s take a look at how the source code is implemented:

  • GitHub: shelljs-rm.js
function rmdirSyncRecursive(dir, force, fromSymlink) {
  
  // 1. Delete all files in the directory first
  let files = fs.readdirSync(dir);
  for (var i = 0; i < files.length; i++) {
    // 1.1 Call rmdirSyncRecursive() recursively for directories
    // 1.2 If it is a file, call fs.unlinksync () to delete it
  }

  // 2. Delete the directory again
  fs.rmdirSync();
}
Copy the code

Of course, there are some details or write a good, here is not to expand in detail, interested partners can click on the above link to explore the source code.

So, let’s use ShellJS method! Replace with system instructions if you feel uncomfortable.

Update the SRC/common/index. Ts

Update the SRC/common/questionList. Ts

Then start writing deletedir.ts:

src/base/file/deleteDir.ts

import shell from 'shelljs';

export const deleteDir = async (path: string): Promise<boolean> => {
  /** * cmd.exe: rd /s /q 
      
        * PowerShell: rd -r 
       
         * Mac: rm -rf 
        
          * ShellJS: Rm () deletes the file, rm('rf', 
         
          ) deletes the folder */
         
  await shell.rm('-rf', path);
  return true;
};
Copy the code

Run NPM run jsliang. The following information is displayed:

All right, that’s it! It is not clear which is faster: Node operation or system instruction

Seven Git operation

Returns the directory

So finally, it’s back to Git.

Surely some people are as lazy as Jsliang?

  • git add .
  • git commit -m "xxx"
  • git push

Jsliang has even developed a specific VS Code plugin:

Note: VS Code is also a volume, the update is too fast for my plugin to accept (to some extent, the latest VS Code does not work with this plugin), so my VERSION of VS Code is locked with V1.53.2, I will update this plugin when I have time

Do a quick commit in the VS Code plugin.

So we want to encapsulate some of the regular Git operations (no need to remember instructions, no need to click on pages, let it run).

7.1 Git Commands commonly used in work

Returns the directory

Jsliang is often used in work, and the corresponding instructions are remembered:

  • git pull: Pull the code and automatically merge it,jsliangI’ll use it on this sidegit pull --rebase origin masterTo pull the remote branch and make changes based on that branch
  • git checkout -b <newBranch>: Cuts a new branch from the current branch
  • git branch -D <branch>: deletes a branch by name
  • git add <files>: Commit to the staging area
  • git commit <description>: Commit to the local repository. If you have any in your warehouseeslintTests and things like that are highly recommendedgit commit -m "xxx" --no-verify(Sometimes I really don’t want to check)
  • git push: Commit to a remote library. The general new branch operation isgit push -- set upstream origin <branch>
  • git cherry-pick <commitHash>: Submit the specified (commit) is applied to other branches
  • git stash: Temporary content. Stores the contents of the staging area on the stack (multiple times)stashCan be passed multiple timespopOut)
  • git stash pop: Checks out the content. willgit stashThe contents of the
  • git reset --soft HEAD^: Rolls back the version and retains the content. thisHEAD^It’s the last version. It could also be writtenHEAD~1(this is the COMMIT ID)

It’s worth mentioning that Jsliang has tried it before: Git Worktree, which can modify multiple versions at the same time.

But it’s no use because it’s too much trouble

You may need to modify multiple branches of the same Git repository at the same time, or you may need to modify branch A with reference to branch B.

It is possible to copy a new repository using Git Clone, but if your repository is large (a few gigabytes), it may be troublesome.

So you have git Worktree with the following command:

#Cut the ABC branch out to another directory, jsliang
#Note: This directory cannot be in the main repositorygit worktree add .. /jsliang ABC # git add [< option >] < path > [< commit >]
#Get help
git worktree -h

#View details for each working tree
git worktree list

#More complete working tree information
# git worktree list --porcelain

#Lock content to prevent it from being automatically deleted
git worktree lock

#To unlock the content
git worktree unlock

#Migrate to a new directorygit worktree move abc .. /jsliang2
#Example Delete a working treegit worktree remove .. /jsliang
#Clear the working tree information
git worktree prune
Copy the code

Git worktree

  • Cut out branches:git worktree add .. /jsliang abc
  • Common operations:git add .,git commit -m "xxx",git push
  • To close a branch:git worktree prune

And, of course, Git setup agents

In the case of scientific Internet access, sometimes Git does not work, cloning or push operation is as slow as, you need to set up Git agent.

  • Set the agent
  1. Git config --global HTTP
  2. Git config --global HTTPS
  • Cancel the agent
  1. git config --global --unset http.proxy
  2. git config --global --unset https.proxy
  • View the agents that have been set
  1. git config --global --get http.proxy
  2. git config --global --get https.proxy

I set git config –global http.proxy http://127.0.0.1:10809 with the scientific Internet proxy software I am using now, and git fluency has been improved a lot.

7.2 Switching Branches

Returns the directory

With that said, let’s get down to business. Let’s do a simple branch switch:

Update the SRC/common/index. Ts

Update the SRC/common/questionList. Ts

Next update gitcheckout. ts:

src/base/shell/gitCheckout.ts

import shell from 'shelljs';

/ * * *@name Switch branches@description * 1. Git checkout ${branch} * 2@param {string} Branch Branch name */
export const gitCheckout = (branch: string): boolean= > {
  if(! shell.which('git')) {
    shell.echo('Error: Please install Git first! ');
    shell.exit(1);
  }

  console.log('Start switching branches:');
  const checkoutResult = shell.exec(`git checkout ${branch}`);
  if(checkoutResult.code ! = =0) {
    shell.echo('Error: Failed to cut branch! ');
    shell.exit(1);
  }

  console.log('Start pulling code, please wait:');
  const pullResult = shell.exec('git pull');
  const { stdout, stderr } = pullResult;
  if (pullResult.code === 0) {
    if (stdout.includes('from the remote, but no such ref was fetched.')) {
      console.log('Your branch is up to date'); }}else if (pullResult.code === 1) {
    if (stderr.includes('There is no tracking information for the current branch.')) {
      console.log('No remote branch exists'); }}return true;
};
Copy the code

Then run: NPM run jsliang and enter the branch name following the command:

At this point, because it’s an arbitrary branch that we typed in, it indicates that the branch switch failed.

Of course, small partners can be based on the real business to load more content inside, here is not to expand the detailed explanation, just do it first ~

Eight summary

Returns the directory

In fact, in the last two days, I have condensed some work processes by summarizing bash commands, but I have not explained them all because I can’t think of a better project example for a while. So if you encounter this situation, please feel free to comment on it and sincerely hope to discuss it with your friends.

So, about ShellJS let’s prepare so a point, later Jsliang in life, work encountered some interesting knowledge to add ~ ~

So, see you next time!

Ix references

Returns the directory

  • GitHub: Shelljs-Unix shell Commands for Node.js
  • 👏 nodejs is the ultimate solution to writing bash scripts!
  • GitHub: Git Worktree
  • Use git Worktree
  • Git Worktree parallel development tests
  • Government and Enterprise Cloud Front-end team: How do I use Git at work
  • SegmentFault: Git Dragon-slayer: Parallel development tests using Git Worktree
  • How To Use a Proxy (VPN) in Git
  • Ruan Yifeng: Cherry pick

Jsliang’s document library is licensed by Jun Rong Liang under a Creative Commons Attribution – Non-Commercial – Share Alike 4.0 International license. Based on the github.com/LiangJunron… On the creation of works. Outside of this license agreement authorized access can be from creativecommons.org/licenses/by… Obtained.